
-----------------------------------
mike200015
Sat Apr 30, 2005 3:13 pm

Help with shooting
-----------------------------------
im working on an addition to my blockout game, when you press space,  bullets shoot from the paddle, and i want them to destroy 1 block and then dissapear, and i want rapid fire. 

I did this so far, but i'm not sure how to get more bullets going at the same time, right now when you press Space, 1 bullet goes, and when you press Space again, the bullet dissapears and another one shoots.
I think i have to do something with flexible arrays, but not quite sure what exactly.

Heres the code:

type block :
    record
        x : int
        y : int
        hits : int
    end record
%type bulletvars :
%    record
%        x : int
%        y : int
%        hits : int
%    end record
var xvalue : int := -15
var yvalue : int := 0
var blocks : array 1 .. 156 of block
var colours : array 1 .. 10 of int := init (40, 50, 60, 70, 80, 90, 100, 110, 120, 130)
var blockcol : array 1 .. 156 of int
%var bullet : array 1 .. 100 of bulletvars
var chars : array char of boolean
var shoot := true
var ballx := maxx div 2
var bally := 15
var pos := maxx div 2
var xmod := 1
var ymod := 1
var tries := 3
var score := 0
var font3 := Font.New ("Courier New:10:bold")         %All other font
var keyPressed : string (1)
var bulbutton := chr (ORD_SPACE)
var bulletx : int := 0
var bullety : int := 8
setscreen ("graphics:640;400,title:Mikes X-Treme Pong Game,nocursor")

process bulletfire
    loop
        % for x : 1 .. 50
        Draw.FillOval (bulletx, bullety, 3, 3, 43)
        bullety += 1
        delay (40)
        % end for
        exit when whatdotcolour (bulletx, bullety + 3) not= 0
    end loop
end bulletfire



for i : 1 .. upper (blocks)
    blocks (i).hits := 0
end for
%for i : 1 .. upper (bullet)
%   bullet (i).x := pos
%    bullet (i).y := 10
%    bullet (i).hits := 0
%end for



loop
    cls
    for i : 1 .. 156
        randint (blockcol (i), 1, 10)
    end for
    setscreen ("offscreenonly")
    loop
        for i : 1 .. 156
            if (i - 1) rem 12 = 0 then
                xvalue += 45
                yvalue := 230
            end if
            blocks (i).x := xvalue
            blocks (i).y := yvalue
            if blocks (i).hits ~= 1 then
                Draw.FillBox (blocks (i).x, blocks (i).y + 2, blocks (i).x + 40, blocks (i).y + 10, colours (blockcol (i)))
            end if
            yvalue += 12
        end for
        Draw.FillBox (pos - 25, 0, pos + 25, 5, 1)         %user paddle
        Font.Draw ("Tries Remaining: " + intstr (tries), 2, maxy - 12, font3, blue)
        Font.Draw ("Score:  " + intstr (score), maxx - 83, maxy - 12, font3, blue)
        Draw.Line (0, maxy - 20, maxx, maxy - 20, RGB.AddColor (0.1, 0.1, 0.1))         %top boundary line
        Input.KeyDown (chars)
        if chars (KEY_LEFT_ARROW) and pos - 25 > 0 then          %Moves paddle left
            pos -= 2
        elsif chars (KEY_RIGHT_ARROW) and pos + 25 < maxx then          %Moves paddle right
            pos += 2
        end if
        if chars (bulbutton) and shoot then
            bulletx := pos
            bullety := 8
            fork bulletfire
            %fork bulletdelay
        end if
        if chars ('x') then
            exit
        elsif chars ('p') then             %Pauses game
            setscreen ("nooffscreenonly")
            Font.Draw ("GAME PAUSED", maxx div 2 - 20, maxy - 12, font3, blue)
            Font.Draw ("*Press ENTER To Resume*", maxx div 2 - Font.Width ("*Press ENTER To Resume*", font3)
                div 2, 100, font3, blue)
            loop
                getch (keyPressed)
                exit when keyPressed = KEY_ENTER
            end loop
            setscreen ("offscreenonly")
        end if
        xvalue := -15
        yvalue := 0
        View.Update
        cls
    end loop
    if chars ('x') then
        exit
    end if
end loop


-----------------------------------
Cervantes
Sat Apr 30, 2005 8:44 pm


-----------------------------------
Yep, flexible arrays is the key here.  Whenever you hit the fire button, you create a new element of the flexible array.  The flexible array should be of a record that contains things such as x and y positions, and x and y velocities or velocity and angle etc.  
In your main loop, you have a for loop from 1 .. upper (bullets) to update the position of all the bullets.  You'll also have to check for collisions with them, and also you'll probably want to put a range limit on them.  Say, if they go 500 pixels, delete them.  That would be done by using startX and startY variables.  You could then Math.Distance, though that's rather slow.  Or you could just run a few if statements.

In any case, check the flexible arrays tutorial, if you don't know how to use them.  If you do, check through the code I've included; it's a good example as to how to do this kind of thing.

-----------------------------------
mike200015
Sat Apr 30, 2005 10:55 pm


-----------------------------------
ok.. thanx.. i got the flexible array to work, but now i have 2 problems:

1. The bullet draws a line sort of, cuz it stretches is when i hold the space.?
2. I have a problem with the collision, i cant figure out how to do it, im using Math.DistancePointLine but i dunno where to put it cuz i gotta check the array of blocks and the array of bullets at the same time but they have 2 different upper values, so i cant really do it in a for loop?? :? 

And 1 more question, how can i get it so i can hold space and it will delay like 1 second and shoot the next bullet so i dont havto keep pressing space?


Heres my new code:
type block :
    record
        x : int
        y : int
        hits : int
    end record
type bulletvars :
    record
        x : int
        y : int
        hits : int
        col : int
    end record
var xvalue : int := -15
var yvalue : int := 0
var blocks : array 1 .. 156 of block
var colours : array 1 .. 10 of int := init (40, 50, 60, 70, 80, 90, 100, 110, 120, 130)
var blockcol : array 1 .. 156 of int
var bullet : flexible array 0 .. 0 of bulletvars
var chars : array char of boolean
var shoot := true
var ballx := maxx div 2
var bally := 15
var pos := maxx div 2
var xmod := 1
var ymod := 1
var tries := 3
var score := 0
var font3 := Font.New ("Courier New:10:bold")         %All other font
var keyPressed : string (1)
var bulbutton := chr (ORD_SPACE)
var bulletx : int := 0
var bullety : int := 8
var yes :=false

setscreen ("graphics:640;400,title:Mikes X-Treme Pong Game,nocursor")

process bulletfire

    loop
        % for x : 1 .. 50
        Draw.FillOval (bulletx, bullety, 3, 3, 43)
        bullety += 1
        delay (40)
        % end for
        exit when whatdotcolour (bulletx, bullety + 3) not= 0
    end loop

end bulletfire



for i : 1 .. upper (blocks)
    blocks (i).hits := 0
end for

%for i : 1 .. upper (bullet)
%   bullet (i).x := pos
%    bullet (i).y := 10
%    bullet (i).hits := 0
%end for



loop
    cls
    for i : 1 .. 156
        randint (blockcol (i), 1, 10)
    end for
    setscreen ("offscreenonly")
    loop
        for i : 1 .. 156
            if (i - 1) rem 12 = 0 then
                xvalue += 45
                yvalue := 230
            end if
            blocks (i).x := xvalue
            blocks (i).y := yvalue
            if blocks (i).hits ~= 1 then
                Draw.FillBox (blocks (i).x, blocks (i).y + 2, blocks (i).x + 40, blocks (i).y + 10, colours (blockcol (i)))
            end if
            yvalue += 12
        end for
        Draw.FillBox (pos - 25, 0, pos + 25, 5, 1)         %user paddle
        Font.Draw ("Tries Remaining: " + intstr (tries), 2, maxy - 12, font3, blue)
        Font.Draw ("Score:  " + intstr (score), maxx - 83, maxy - 12, font3, blue)
        Draw.Line (0, maxy - 20, maxx, maxy - 20, RGB.AddColor (0.1, 0.1, 0.1))         %top boundary line
        Input.KeyDown (chars)
        if chars (KEY_LEFT_ARROW) and pos - 25 > 0 then          %Moves paddle left
            pos -= 2
        elsif chars (KEY_RIGHT_ARROW) and pos + 25 < maxx then          %Moves paddle right
            pos += 2
        end if
        if chars (bulbutton) and shoot then
         
            new bullet, upper (bullet) + 1
            yes :=true
            %fork bulletfire
            %fork bulletdelay
        end if
        if chars ('x') then
            exit
        elsif chars ('p') then             %Pauses game
            setscreen ("nooffscreenonly")
            Font.Draw ("GAME PAUSED", maxx div 2 - 20, maxy - 12, font3, blue)
            Font.Draw ("*Press ENTER To Resume*", maxx div 2 - Font.Width ("*Press ENTER To Resume*", font3)
                div 2, 100, font3, blue)
            loop
                getch (keyPressed)
                exit when keyPressed = KEY_ENTER
            end loop
            setscreen ("offscreenonly")
        end if
        for i : upper (bullet) .. upper (bullet)
            bullet (i).col := 43
            bullet (i).x := pos
            bullet (i).y := 8
            bullet (i).hits := 0
        end for
        for i : lower (bullet) .. upper (bullet)
            if yes = true then
                Draw.FillOval (bullet (i).x, bullet (i).y, 3, 3, bullet (i).col)
                if bullet (i).hits ~= 1 then
                    bullet (i).y += 1
                end if
                /*
                 if Math.DistancePointLine (bullet (i).x, bullet (i).y, blocks (i).x, blocks (i).y, blocks (i).x + 40, blocks (i).y)  0 then          %Moves paddle left
            pos -= 2
        elsif chars (KEY_RIGHT_ARROW) and pos + 25 < maxx then          %Moves paddle right
            pos += 2
        end if
        if chars (bulbutton) and shoot then

            new bullet, upper (bullet) + 1
            yes := true
            %fork bulletfire
            %fork bulletdelay
        end if
        if chars ('x') then
            exit
        elsif chars ('p') then             %Pauses game
            setscreen ("nooffscreenonly")
            Font.Draw ("GAME PAUSED", maxx div 2 - 20, maxy - 12, font3, blue)
            Font.Draw ("*Press ENTER To Resume*", maxx div 2 - Font.Width ("*Press ENTER To Resume*", font3)
                div 2, 100, font3, blue)
            loop
                getch (keyPressed)
                exit when keyPressed = KEY_ENTER
            end loop
            setscreen ("offscreenonly")
        end if
        for i : upper (bullet) .. upper (bullet)
            bullet (i).col := 43
            bullet (i).x := pos
            bullet (i).y := 8
            bullet (i).hits := 0
        end for
        for i : lower (bullet) .. upper (bullet)
            if yes = true then
                if bullet (i).y = 10 and bullet (x).y = timeDelay then
        result true
    end if
    result false
end cooldown

for i : 1 .. upper (blocks)
    blocks (i).hits := 0
end for


loop
    cls
    for i : 1 .. 156
        randint (blockcol (i), 1, 10)
    end for
    setscreen ("offscreenonly")
    loop
        for i : 1 .. 156
            if (i - 1) rem 12 = 0 then
                xvalue += 45
                yvalue := 190
            end if
            blocks (i).x := xvalue
            blocks (i).y := yvalue
            if blocks (i).hits ~= 1 then
                Draw.FillBox (blocks (i).x, blocks (i).y + 2, blocks (i).x + 40, blocks (i).y + 10, colours (blockcol (i)))
            end if
            yvalue += 12
        end for
        Draw.FillBox (pos - 25, 0, pos + 25, 5, 1)         %user paddle
        Font.Draw ("Tries Remaining: " + intstr (tries), 2, maxy - 12, font3, blue)
        Font.Draw ("Score: " + intstr (score), maxx - 83, maxy - 12, font3, blue)
        Font.Draw ("Bullets: " + intstr (bammo), maxx - (135 + Font.Width ("Bullets: ", font3)), maxy - 12, font3, blue)
        Font.Draw ("Missiles: " + intstr (mammo), maxx - (252 + Font.Width ("Missiles: ", font3)), maxy - 12, font3, blue)
        Draw.Line (0, maxy - 20, maxx, maxy - 20, RGB.AddColor (0.1, 0.1, 0.1))         %top boundary line
        Input.KeyDown (chars)
        if chars (KEY_LEFT_ARROW) and pos - 25 > 0 then          %Moves paddle left
            pos -= 2
        elsif chars (KEY_RIGHT_ARROW) and pos + 25 < maxx then          %Moves paddle right
            pos += 2
        end if
        if bammo > 0 then
            if chars (bulbutton) then
                if cooldown (300) then
                    new bullet, upper (bullet) + 1
                    bullet (upper (bullet)).col := 43
                    bullet (upper (bullet)).x := pos
                    bullet (upper (bullet)).y := 8
                    bullet (upper (bullet)).hits := 0
                    timeLast := Time.Elapsed
                    bammo -= 1
                end if
            end if
        end if
        if mammo > 0 then
            if chars (KEY_SHIFT) then
                if cooldown (300) then
                    new missile, upper (missile) + 1
                    missile (upper (missile)).col := 43
                    missile (upper (missile)).x := pos
                    missile (upper (missile)).y := 8
                    missile (upper (missile)).hits := 0
                    timeLast := Time.Elapsed
                    mammo -= 1
                end if
            end if
        end if
        if chars ('x') then
            exit
        elsif chars ('p') then             %Pauses game
            setscreen ("nooffscreenonly")
            Font.Draw ("GAME PAUSED", maxx div 2 - 44, 140, font3, blue)
            Font.Draw ("*Press ENTER To Resume*", maxx div 2 - Font.Width ("*Press ENTER To Resume*", font3)
                div 2, 100, font3, blue)
            loop
                getch (keyPressed)
                exit when keyPressed = KEY_ENTER
            end loop
            setscreen ("offscreenonly")
        end if
        for i : 1 .. upper (bullet)
            if bullet (i).y = 10 and missile (x).y = blocks (i).x and missile (x).x - 5 = blocks (i).y then
                            blocks (i).hits := 1
                            missile (x).hits += 1
                            missile (x).col := 0
                            score += 1
                            for k : x + 1 .. upper (missile)
                                missile (k - 1) := missile (k)
                            end for
                            new missile, upper (missile) - 1
                            exit
                        end if
                    end if
                end for
            end if
        end for
        xvalue := -15
        yvalue := 0
        %delay (4)
        View.Update
        cls
    end loop
    if chars ('x') then
        exit
    end if
end loop


-----------------------------------
Cervantes
Mon May 02, 2005 6:09 pm


-----------------------------------
The reason for this is as follows:
We are going to examine this section of code:

        %bullet and block collision
        for x : 1 .. upper (bullet)
            if bullet (x).y >= 10 and bullet (x).y = blocks (i).x and bullet (x).x = blocks (i).y then
                            blocks (i).hits := 1
                            bullet (x).hits := 1
                            bullet (x).col := 0
                            score += 1
                            %exit
                            for k : x + 1 .. upper (bullet)
                                bullet (k - 1) := bullet (k)
                            end for
                            new bullet, upper (bullet) - 1
                            exit
                        end if
                    end if
                end for
            end if
        end for

Let's assume all those if statements are true.  We go all the way into it, and we delete that particular bullet.  Then we exit the for loop that checks the blocks, and restart at the top of the bullet's for loop.  But now we've got one less bullet, and yet x has still increased.  Thus, x is now > upper (bullet), because we decreased upper (bullet).

To fix this, check out the tut about [url=http://www.compsci.ca/v2/viewtopic.php?t=7390]Removing an Element from a Flexible Array within a For Loop.  It's not a great tutorial, mind you, because it was really a question I posted in Help that got kinda got transformed into a tutorial.  I don't even know the best solution to the problem: as you'll soon find out, I took Bacchus idea, and fixed it so it would work in a few more situations than his original idea did.  But by doing this I also used lots of cpu processing, which is really bad in your case.
In any case, read the tutorial, and maybe you can spend some time on the problem and post the best solution.  :)

-----------------------------------
mike200015
Mon May 02, 2005 9:06 pm


-----------------------------------
k.. ill check out the tutorial, thanx!

And also, about the 2D array for the blocks that you said to do, how should i change my blocks now to make it like you suggested? :?

-----------------------------------
mike200015
Mon May 02, 2005 9:37 pm


-----------------------------------
i took out the line 
new bullet, upper (bullet)-1
it prevents the error of array subscript out of range coming up, but then the last  bullet of the array doesnt stop, it destroys all the blocks in its row.

-----------------------------------
mike200015
Mon May 02, 2005 9:54 pm


-----------------------------------
nevermind, i got it to work, i jus added the suggestion that Bacchus gave in your question, i added in:
exit when x+1>upper (bullet)and it works fine,  :lol: i was trying other things cuz i didnt think that would work, and then i tried it, and it worked! Thanx so much Cervantes, and Bacchus with your idea! lol

The only thing still, is that i thought by doing the whole thing with deleting the upper, it would prevent my game from slowing down, but it doesnt really, i dont think. After i shoot alot of bullets, then it slows down my game permanently. How would i prevent this from happening?

-----------------------------------
Bacchus
Tue May 03, 2005 5:54 am


-----------------------------------
prevent them from shooting that much :P, id also suggest a cooldown for shotting so that when they press the button once, they dont shoot like 5 times. and.. what did i do?

-----------------------------------
Cervantes
Tue May 03, 2005 9:39 am


-----------------------------------
I don't know about the game slowing down.  I don't think you can use the free command with flexible arrays (only with classes and collections).  I would have thought that Turing would automatically free some memory up when you delete an element of the array.  Are you absolutely certain that this is the cause of your program slowing down?

-----------------------------------
mike200015
Tue May 03, 2005 4:18 pm


-----------------------------------
i realized the game didnt slow down after shooting alot of bullets,  :oops:  :P , i thought it was.. seemed like it lol.
Anyways, I needed to delete bullets on screen that havent hit anything yet, at another point during my game, and i used the free command and it worked to delete it from the screen. I jus wanted to know if the free actually deletes the bullet from the array. 
For example, my array is at 1..0 at beginning, and i shoot a bullet, and my array is at 1..1, if i use free, will it now make my array 1..0 again?

-----------------------------------
Bacchus
Tue May 03, 2005 6:03 pm


-----------------------------------
use new again to altar the array back, think it should delete everything

-----------------------------------
mike200015
Tue May 03, 2005 7:21 pm


-----------------------------------
what i need to do is set my array again to 0, so i should do:
new bullet, upper (bullet) 0 ??
can i set the upper to a certain number using new?.. or is new only for adding / subtracting? Cuz i dunno how many to subtract, so i need to just set it to 0

-----------------------------------
mike200015
Tue May 03, 2005 7:24 pm


-----------------------------------
oo.. do i do this, to set upper as something: ?
new bullet, 0

-----------------------------------
Cervantes
Tue May 03, 2005 7:27 pm


-----------------------------------
That's correct.

-----------------------------------
mike200015
Tue May 03, 2005 8:58 pm


-----------------------------------
wats better to do.. the free command, or the new command?

Also, im attaching my game in a zip, which is the blockout game with bullets and ball.. Please post your comments about what you think of it, as well.. if anyone knows how to fix the ball and paddle collision, so that the ball doesnt slide sometimes on the paddle, I'd really appreciate it.

-----------------------------------
jamonathin
Wed May 04, 2005 7:00 am


-----------------------------------
Game looks good. I never ran into that paddle slide thing problem.  Ball moves pretty fast though, or maybe Im just bad at pong  :? .  But the games lookin good, keep it up. :)

-----------------------------------
mike200015
Wed May 04, 2005 4:33 pm


-----------------------------------
:D thanx jamonathin and yea.. the ball sliding on the paddle only happens sometimes

-----------------------------------
mike200015
Wed May 04, 2005 4:34 pm


-----------------------------------
Question : How can i check the full circumference of the ball, right now it just checks the top bottom and sides.??

-----------------------------------
Cervantes
Wed May 04, 2005 7:42 pm


-----------------------------------
Check the full circumfrence?  Use the formula for a circle: 
(x - h)^2 + (y - k)^2 = r^2.
Of course, you don't want EVERY point.  You probably really only want four points.  It's probably easiest to just do a few more if statements.

-----------------------------------
mike200015
Wed May 04, 2005 7:45 pm


-----------------------------------
i need to check more than the four points that i'm checking now, because, when the ball hits the paddle at an angle, on the corner of the paddle, the ball wont bounce off, it just sort of goes through the paddle, and hits the bottom of the screen. And also with the blocks, when the ball hits the corner of a block, it just goes through it.

-----------------------------------
Chaos_Simon
Sat May 07, 2005 7:43 pm

...
-----------------------------------
very inerestng...but for some reason it dosenst work well on my computer...why?
