%Created by Adam Bielinski
%Just a simple program that imitates the windows screensaver
%it looks better, and the center is at the mouse, and not the center of the screen
%if you want, you can change these two variables to resize the effective screen
const X_SCREEN := 1024
const Y_SCREEN := 768
View.Set ("noecho")
View.Set ("nobuttonbar")
View.Set ("title:Stars 3D by Adam Bielinski")
Mouse.ButtonChoose ("multibutton")
View.Set ("graphics:" + intstr (X_SCREEN) + ";" + intstr (Y_SCREEN))
View.Set ("position:centre,middle")
View.Set ("offscreenonly")
Draw.FillBox (-10, -10, X_SCREEN, Y_SCREEN, black)
%number of stars. if you're getting a slowdown, decrease this
const NUM_STARS := 400
%speed ratio of the stars... this should be modified in conjuction with STAR_LIFE
%... i think the relationship is about right... linear seems right
var star_absolute_speed : real := 0.4 %this is only a starting value
const MAX_ABSOLUTE_SPEED := 50 %max speed
%how relatively big the stars are
const STAR_SIZE := 6
%how fast the stars fly away fromt the center
const STAR_ACC := 0.1
const SMALL_STAR_COLOR := 17 %should be between 16 and 31
%increase this number to make the "lag" on the mouse increase
const MOUSE_SMOOTHING := 5
%how fast the mouse can accelerate the user
const MOUSE_ACC := 0.03
type point_type :
record
x : real
y : real
life : real
end record
var stars : array 1 .. NUM_STARS of point_type
var old_stars : array 1 .. NUM_STARS of point_type
%this is the initialatation stuff. It just puts them around on the screen at random
for lp : 1 .. NUM_STARS
stars (lp).x := Rand.Int (1, X_SCREEN)
stars (lp).y := Rand.Int (1, Y_SCREEN)
stars (lp).life := 0
end for
old_stars := stars
procedure DrawStar (x1, y1, x2, y2, life : real)
%sinxe the shades of gray are nubmers 16 to 31, this finds the color that is needed for the first oval
const temp_clr := round ((life) mod 15 + 16)
const temp_size := floor (life / 15)
%this makes sure the star is visible
if temp_size < 1 and temp_clr < SMALL_STAR_COLOR then
Draw.Line (round (x1), round (y1), round (x2), round (y2), SMALL_STAR_COLOR)
else
%this oval is the oval that makes the change in size smooth
%it does this by being a shade of gray that makes the other oval appear slightly larger
Draw.ThickLine (round (x1), round (y1), round (x2), round (y2),
temp_size + 1, temp_clr)
end if
if temp_size >= 1 then
Draw.ThickLine (round (x1), round (y1), round (x2), round (y2),
temp_size, white)
end if
end DrawStar
var temp_string : string := ""
temp_string := "Click Here"
var font : int := Font.New ("Times:28")
%this waits for the user to click... it jsut has "click here" so that the effect is more impressive
Font.Draw (temp_string, X_SCREEN div 2 - Font.Width (temp_string, font) div 2, Y_SCREEN div 2, font, white)
temp_string := "click the mosue to change speeds"
Font.Draw (temp_string, X_SCREEN div 2 - Font.Width (temp_string, font) div 2, Y_SCREEN div 2 - 100, font, white)
View.Update
loop
exit when Mouse.ButtonMoved ("downup")
end loop
var mouse_x, mouse_y, button : int := 0
var old_mouse_x, old_mouse_y : real := 0 %this is the blue dot... where the stars really fly from
var last_time : real := Time.Elapsed
loop
Mouse.Where (mouse_x, mouse_y, button)
if button = 1 then %if user clicks left, speed up
star_absolute_speed *= 1 + MOUSE_ACC
elsif button = 100 then %if user clicks right, slow down
star_absolute_speed *= 1 - MOUSE_ACC
end if
%if speed is too great, slow down
if star_absolute_speed > MAX_ABSOLUTE_SPEED then
star_absolute_speed := MAX_ABSOLUTE_SPEED
end if
%how fast the stars grow in size
%this is the equation used... not really sure why this is it. I got this from trial and error
const STAR_LIFE := (1 + star_absolute_speed / 10) ** 0.1
%I will be replacing the literals with constants
old_mouse_x := (old_mouse_x * (MOUSE_SMOOTHING - 1) + mouse_x) / MOUSE_SMOOTHING
old_mouse_y := (old_mouse_y * (MOUSE_SMOOTHING - 1) + mouse_y) / MOUSE_SMOOTHING
drawdot (round (old_mouse_x), round (old_mouse_y), brightblue)
for lp : 1 .. NUM_STARS
%this stuff moves the stars
stars (lp).x := (stars (lp).x - old_mouse_x) *
(stars (lp).life * STAR_ACC * star_absolute_speed + 1) + old_mouse_x
stars (lp).y := (stars (lp).y - old_mouse_y) *
(stars (lp).life * STAR_ACC * star_absolute_speed + 1) + old_mouse_y
%this increases the star's "life"
stars (lp).life := (stars (lp).life + 1) * STAR_LIFE - 1
%this draws the star
DrawStar (stars (lp).x, stars (lp).y, old_stars (lp).x, old_stars (lp).y, (stars (lp).life * STAR_SIZE) ** 2)
%if the star is outside the screen, reinitialize it
if stars (lp).x < 0 or stars (lp).x > X_SCREEN or stars (lp).y < 0 or stars (lp).y > Y_SCREEN then
stars (lp).x := Rand.Real * X_SCREEN
stars (lp).y := Rand.Real * Y_SCREEN
stars (lp).life := 0
end if
end for
%make the trailing edge become equal to the old star values
old_stars := stars
View.Update
%drawfillbox (-10, -10, X_SCREEN, Y_SCREEN, black) %erase the screen
%This is a cool alternative to drawfillbox
for lp : 1 .. 400 %this number tells how fast the backround is erased (num of lines)
drawline (Rand.Int (1, X_SCREEN) * 2 - X_SCREEN div 2, Rand.Int (1, Y_SCREEN) * 2 - Y_SCREEN div 2,
Rand.Int (1, X_SCREEN) * 2 - X_SCREEN div 2,
Rand.Int (1, Y_SCREEN) * 2 - Y_SCREEN div 2, black)
end for
%this section controls the timing of the program
loop
exit when Time.Elapsed - last_time > 30 %wait for the time
end loop
last_time := Time.Elapsed
end loop
|