
-----------------------------------
Windsurfer
Sun Jul 02, 2006 12:21 pm

Forces Engine
-----------------------------------
For those of you who may have seen my Forces game, here's the basic "engine" I started off with for the sparkles. It was made a while ago, so of course, it's not quite how i program now  :lol:  but it still works, and can be fun to just play around with.


%Created by Adam Bielinski
%this is the basic engine for Bielin_Forces
%this was written early in my learning of turing, so it's messy and not commented


% --------------------------------
%the conrols are: Spacebar, z, x, c, and all the mouse buttons
% -------------------------------


%try it out! see what you can do!


View.Set ("nocursor")
View.Set ("noecho")

Mouse.ButtonChoose ("multibutton")

setscreen ("graphics:800;600")
drawline (1, 1, 1, 1, black)
View.Set ("offscreenonly")

var back_color : int := black

%Change either of these to a lower number if you're getting a slowdown
const NUM_SPKL := 500 %this is the max number of sparkles
const SPKL_RATIO := 10 %this is how many sparkles are made by clicking


const SPKL_LIFE := 2500

drawfillbox (-10, -10, 810, 610, back_color) %erases the screen
const AIR_RES := 1.05 %how fast the sparkles slow down (make it less than 1 to make them speed up!)

const SPKL_GRAV := -0.94 %how fast they accelerate in th y plane

const EXPL_FORCE := 600 %something to do with how powerful the World_Force procedure is.... hmm...
type vector :
    record
        x : real
        y : real
        x_vel : real
        y_vel : real
        life : int
        clr : int
    end record

var cur_spkl : int := 1
var spkl : array 1 .. NUM_SPKL of vector
for lp : 1 .. NUM_SPKL
    spkl (lp).x := 0
    spkl (lp).y := 0
    spkl (lp).x_vel := 0
    spkl (lp).y_vel := 0
    spkl (lp).life := SPKL_LIFE
end for


var global_clr : int := white

procedure Draw_Spkl (num, colour : int)
    %drawfilloval (round (spkl (num).x), round (spkl (num).y), 3, 3, colour)
    var dir_x, dir_y, dist : real := 0
    dist := sqrt (spkl (num).x_vel ** 2 + spkl (num).y_vel ** 2)
    if dist ~= 0 then
        dir_x := ((spkl (num).x_vel / dist * 10) + spkl (num).x_vel)
        dir_y := ((spkl (num).y_vel / dist * 10) + spkl (num).y_vel)
    end if
    drawline (round (spkl (num).x), round (spkl (num).y),
        round (spkl (num).x - dir_x), round (spkl (num).y - dir_y), colour)
end Draw_Spkl

procedure Run_Sparkle
    for lp : 1 .. NUM_SPKL by 1
        if spkl (lp).life < SPKL_LIFE then % if the sparkle needs processing, process it
            %Draw_Spkl (lp, back_color)
            spkl (lp).life += 1 %decrease the life of the sparkle
            spkl (lp).y_vel := (spkl (lp).y_vel + SPKL_GRAV) / AIR_RES
            spkl (lp).x_vel := spkl (lp).x_vel / AIR_RES
            spkl (lp).y := (spkl (lp).y + spkl (lp).y_vel)
            spkl (lp).x := (spkl (lp).x + spkl (lp).x_vel)
            if spkl (lp).y < -50 then
                spkl (lp).life := SPKL_LIFE
            end if
            if spkl (lp).life < SPKL_LIFE then
                Draw_Spkl (lp, spkl (lp).clr)
            end if
        else
            %do nothing
        end if
    end for
end Run_Sparkle


function SpklCount : int %how many sparkles are alive?
    var temp1 : int := 1
    for lp : 1 .. NUM_SPKL by 1
        if spkl (lp).life < SPKL_LIFE then
            temp1 += 1
        else
            %do nothing
        end if
    end for
    result temp1
end SpklCount

procedure Mk_Spkl (x1, y1 : real) %make a sparkle at a point in a random direction
    var angle : real
    var mag : real
    if cur_spkl > NUM_SPKL then
        cur_spkl := 1
    end if
    Draw_Spkl (cur_spkl, back_color)
    spkl (cur_spkl).clr := global_clr
    spkl (cur_spkl).life := 1
    spkl (cur_spkl).x := x1
    spkl (cur_spkl).y := y1
    angle := Rand.Int (1, 360)
    mag := Rand.Int (1, 120) / 10
    spkl (cur_spkl).x_vel := mag * cosd (angle)
    spkl (cur_spkl).y_vel := mag * sind (angle) + 5
    %this gives the sparkles a shot upwards
    cur_spkl += 1
end Mk_Spkl

procedure Mk_Spkl_Custom (x1, y1, x2, y2 : real) %make a sparkle at a point going in a specific direction with a specific speed
    if cur_spkl > NUM_SPKL then
        cur_spkl := 1
    end if
    Draw_Spkl (cur_spkl, back_color)
    spkl (cur_spkl).clr := global_clr
    spkl (cur_spkl).life := 1
    spkl (cur_spkl).x := x1
    spkl (cur_spkl).y := y1
    spkl (cur_spkl).x_vel := x2
    spkl (cur_spkl).y_vel := y2
    %this gives the sparkles a shot upwards
    cur_spkl += 1
end Mk_Spkl_Custom


procedure World_Force (h1, v1 : int, num : real)
    %this forces ALL sparkles using gravity (or colomb's law, whichever you want)
    %this is a horrible medly of math X(
    %it could Easily be simplified, but it works, and i don't feel like it lol
    var dist : real
    for lp : 1 .. NUM_SPKL
        dist := sqrt ((spkl (lp).x - h1) ** 2 + (spkl (lp).y - v1) ** 2)
        if round (spkl (lp).x) not= h1 then
            spkl (lp).x_vel += ((spkl (lp).x - h1) / ((dist ** 2) /
                EXPL_FORCE)) * (num / 30)
        end if
        if round (spkl (lp).y) not= v1 then
            spkl (lp).y_vel += ((spkl (lp).y - v1) / ((dist ** 2) /
                EXPL_FORCE)) * (num / 30)
        end if
    end for
end World_Force


%general var declarations
var mouse_x, mouse_y, button, left, middle, right : int
var last_time : real
var chars : array char of boolean
var key_press_temp : int := 0

last_time := Time.Elapsed

%    MAIN LOOOOOOP
loop
    key_press_temp -= 1 %this var controls if you can press a key
    if key_press_temp < 0 then
        key_press_temp := 0
    end if
    Mouse.Where (mouse_x, mouse_y, button)

    Input.KeyDown (chars)
    if chars (' ') and key_press_temp 