
-----------------------------------
chrisbrown
Tue May 22, 2007 6:37 pm

Guitar Hero
-----------------------------------
My work-in-progress: this version has no music, no beginning or ending, nor any order to the frets hit points.


%Guitar Hero 0.5
%By Chris Brown
%Based directly on the Guitar Hero games (no sh!t)
%NOT based on Frets on Fire (since I haven't played it yet)
%See scoring below

View.Set ("graphics:max;max;offscreenonly;nocursor")

%Performance/Gameplay
const COMP_SPEED := 6   %Resolution of movement, among else
const DELAY := 20       %Time (in ms) between main program loop cycles
const DIFF := 50        %Difficulty/spacing between consecutive fret hit nodes, low
const HIT_LOC := 40     %Depth, in pixels, of the fixed fret points
const NODES := 20       %Number of fret hit nodes
const SPEED := 5        %Speed, in pixels per cycle, of the fret hit nodes
const maxz := 500       %Depth of Z-axis

%Controls: de-comment your preferred methoed
const STRUM : char := KEY_ENTER
const KEYS : array 1 .. 5 of char := init ('1', '2', '3', '4', '5')
%const KEYS : array 1 .. 5 of char := init ('`', '1', '2', '3', '4')

%Scoring
const HIT := 1000       %Increase for each good fret hit
const ALMOST := 1       %Slight decrease
const MISS := 100       %Complete miss
const OVERSTRUM := 1    %Decrease every time enter is held down

%Display
const LINE_WIDTH := 5   %Spacing between wall lines
const H := 20           %Height of fret hit points
const W := 40           %Width of fret hit points

%Colors
RGB.SetColour (200, .8, .1, .1)
RGB.SetColour (201, .1, .1, .8)
RGB.SetColour (202, .1, .8, .1)
RGB.SetColour (203, .8, .8, .1)
RGB.SetColour (204, 1, .6, .1)
RGB.SetColour (205, .4, .05, .05)
RGB.SetColour (206, .05, .05, .4)
RGB.SetColour (207, .05, .4, .05)
RGB.SetColour (208, .4, .4, .05)
RGB.SetColour (209, .5, .3, .05)
const RED : int := 200
const BLUE : int := 201
const GREEN : int := 202
const YELLOW : int := 203
const ORANGE : int := 204
const DARKRED : int := 205
const DARKBLUE : int := 206
const DARKGREEN : int := 207
const DARKYELLOW : int := 208
const DARKORANGE : int := 209
const C1 : array 1 .. 5 of int := init (GREEN, RED, YELLOW, BLUE, ORANGE)
const C2 : array 1 .. 5 of int := init (DARKGREEN, DARKRED, DARKYELLOW, DARKBLUE, DARKORANGE)

%Misc globals - no need to change
type Point2D :
    record
        x, y : real
    end record

type Point3D :
    record
        x, y, z : real
    end record

type Node :
    record
        p : Point3D
        n : int
        t : int
        hit : boolean
    end record

var keys : array char of boolean
var score : int := 0
var song : string
var mult : int := 1
var node : array 1 .. NODES of Node

process playSong (s : string)
    Music.PlayFile (s)
end playSong

%Convert 3D to 2D from Point3D record
fcn to2DFromPoint (threed : Point3D) : Point2D
    var twod : Point2D
    twod.x := maxx div 2 + (threed.x - maxx div 2) / (1 + (threed.z / 100))
    twod.y := maxy div 2 + (threed.y - maxy div 2) / (1 + (threed.z / 100))
    result twod
end to2DFromPoint

%Convert 3D to 2D from x, y, z coordinates
fcn to2D (x, y, z : real) : Point2D
    var twod : Point2D
    twod.x := maxx div 2 + (x - maxx div 2) / (1 + (z / 100))
    twod.y := maxy div 2 + (y - maxy div 2) / (1 + (z / 100))
    result twod
end to2D

%Draws everything
proc draw (dir : int)
    const f := Font.New ("Arial:20")
    Draw.FillBox (0, 0, maxx, maxy, black)
    %White hit point lines
    Draw.ThickLine (round (to2D (0, 0, HIT_LOC - sqrt (DIFF * 2)).x),
        round (to2D (0, 0, HIT_LOC - sqrt (DIFF * 2)).y),
        round (to2D (maxx, 0, HIT_LOC - sqrt (DIFF * 2)).x),
        round (to2D (maxx, 0, HIT_LOC - sqrt (DIFF * 2)).y), 5, white)
    Draw.ThickLine (round (to2D (0, 0, HIT_LOC + sqrt (DIFF * 2)).x),
        round (to2D (0, 0, HIT_LOC + sqrt (DIFF * 2)).y),
        round (to2D (maxx, 0, HIT_LOC + sqrt (DIFF * 2)).x),
        round (to2D (maxx, 0, HIT_LOC + sqrt (DIFF * 2)).y), 5, white)
    for z : 1 .. maxz by round (SPEED * LINE_WIDTH)
        Draw.Box (round (to2D (0, 0, z - (Time.Elapsed mod (SPEED * LINE_WIDTH - 1)) * dir).x),
            round (to2D (0, 0, z - (Time.Elapsed mod (SPEED * LINE_WIDTH - 1)) * dir).y),
            round (to2D (maxx, maxy, z - (Time.Elapsed mod (SPEED * LINE_WIDTH - 1)) * dir).x),
            round (to2D (maxx, maxy, z - (Time.Elapsed mod (SPEED * LINE_WIDTH - 1)) * dir).y), blue)
    end for
    %bottom lines
    for x : 50 .. maxx - 50 by maxx div 6
        Draw.ThickLine (x, 0, round (to2D (x, 0, maxz).x), round (to2D (x, 0, maxz).y), 3, brightgreen)
    end for
    %Hit points
    for i : 1 .. 5
        %Hit point
        for j : 1 .. 3
            if keys (KEYS (i)) then
                Draw.FillOval (round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).x),
                    round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).y),
                    W, H, C2 (i))
                Draw.Oval (round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).x),
                    round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).y + j),
                    W + j, H, C1 (i))
            else
                Draw.Oval (round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).x),
                    round (to2D ((maxx - (maxx div 5)) div 5 * i, 0, HIT_LOC).y + j),
                    W + j, H, C1 (i))
            end if
        end for
    end for
    %Nodes
    for i : 1 .. upper (node)
        if node (i).p.z < maxz then
            %White surrounding
            Draw.FillOval (round (to2DFromPoint (node (i).p).x),
                round (to2DFromPoint (node (i).p).y),
                min (W, round (W ** 1.5 / sqrt (node (i).p.z))),
                min (H, round (H ** 1.5 / sqrt (node (i).p.z))), grey)
            %Dark outline
            Draw.FillOval (round (to2DFromPoint (node (i).p).x),
                round (to2DFromPoint (node (i).p).y + 1),
                min (W - 3, round ((W - 3) ** 1.5 / sqrt (node (i).p.z))),
                min (H - 3, round ((H - 3) ** 1.5 / sqrt (node (i).p.z))), C2 (node (i).n))
            %Main body
            Draw.FillOval (round (to2DFromPoint (node (i).p).x),
                round (to2DFromPoint (node (i).p).y + 2),
                min (W - 4, round ((W - 4) ** 1.5 / sqrt (node (i).p.z))),
                min (H - 3, round ((H - 3) ** 1.5 / sqrt (node (i).p.z))), C1 (node (i).n))
            %Top outline
            Draw.FillOval (round (to2DFromPoint (node (i).p).x),
                round (to2DFromPoint (node (i).p).y + 4),
                min (W div 2, round ((W div 2) ** 1.5 / sqrt (node (i).p.z))),
                min (H div 2, round ((H div 2) ** 1.5 / sqrt (node (i).p.z))), C2 (node (i).n))
            %Top body
            Draw.FillOval (round (to2DFromPoint (node (i).p).x),
                round (to2DFromPoint (node (i).p).y + 5),
                min ((W div 2) - 1, round (((W div 2) - 1) ** 1.5 / sqrt (node (i).p.z))),
                min ((H div 2) - 1, round (((H div 2) - 1) ** 1.5 / sqrt (node (i).p.z))), grey)

        end if
    end for
    put "Score: ", score, " Mult: ", mult
end draw

%Initialize array of hit nodes
for i : 1 .. NODES
    node (i).n := Rand.Int (1, 5)
    node (i).p.x := (maxx - (maxx div 5)) div 5 * node (i).n
    node (i).p.y := 0
    node (i).p.z := HIT_LOC + ((DIFF * Rand.Int (0, 3) * i))
end for

%Execution
loop
    cls
    Input.KeyDown (keys)
    for i : 1 .. NODES
        %Move each node
        node (i).p.z -= SPEED
        %Reset appropriate nodes to back of queue in random location
        if node (i).p.z 