# making the player move smoother

• ### Question

• ```gh = 500
gw = 500
GraphicsWindow.Height=gh
GraphicsWindow.Width = gw
GraphicsWindow.CanResize = "False"
GraphicsWindow.KeyDown = move
GraphicsWindow.KeyUp = stop
frames = 60 ' really smooth
playerx = Math.GetRandomNumber(gh)
playery = Math.GetRandomNumber(gh)
pdX = 2
pdY= 2
Shapes.Move(player, playerx, playery)

numEnemy =1
For i = 0 to (numEnemy-1)
createenemy()

endfor

Sub createenemy
velX[i] = Math.GetRandomNumber(2)
velY[i] = Math.GetRandomNumber(2)

enemyx[i] = Math.GetRandomNumber(gh-15)
enemyy[i] = Math.GetRandomNumber(gh-15)

endsub

While 1=1
moveenemy()
checkcollisionofplayer()
Program.Delay((1000/frames))
endwhile

EndSub
Sub moveenemy
For i = 0 To numEnemy step 1 ' going through all the objects
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

If (ex >= gw-10) Or ( ex < 0) Then
velX[i] = velX[i] * -1
else
velX[i] = velX[i]
endif

If (ey >= gh - 10) Or ( ey < 0) Then
velY[i] = velY[i] * -1
Else
velY[i] = velY[i]

EndIf

enemyx[i] = enemyx[i]+ velX[i]
enemyy[i] = enemyy[i] + velY[i]
Shapes.Move(enemy[i], enemyx[i], enemyy[i])

endfor
endsub

Sub move
key = GraphicsWindow.LastKey
If (key = "A") then
pdX = -5
pdY=0
ElseIf (key = "D") then
pdX =5
pdY=0
elseif (key = "W") then
pdY = -5
pdX =0
elseif(key = "S") then
pdY =5
pdX =0
EndIf

If(Shapes.GetLeft(player) <0) or (Shapes.GetLeft(player) > (gw-15)) Then

If(Shapes.GetLeft(player) <0) Then
playerx = 0
ElseIf(Shapes.GetLeft(player) > (gw-15)) then
playerx = gw -15
EndIf
Else
playerx = playerx+pdX
EndIf
If((Shapes.Gettop(player) <0) or (Shapes.Gettop(player) > (gh-15))) Then

If(Shapes.Gettop(player) <0) Then
playery = 0
ElseIf(Shapes.Gettop(player) > (gh-15)) then
playery = (gh-15)
EndIf
Else
playery = playery + pdY
EndIf

Shapes.Move(player, playerx, playery)

EndSub
Sub checkcollisionofplayer

py = Shapes.GetTop(player)
px = Shapes.GetLeft(player)
For i = 0 To numEnemy
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

'checks for top left
If ((ey >= py) and (ey <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
TextWindow.WriteLine("hit")
EndIf
EndIf
'checks for top right
If ((ey >= py) and (ey <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
TextWindow.WriteLine("hit")
EndIf
EndIf
'checks for bottom right
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
TextWindow.WriteLine("hit")
EndIf
EndIf
'checks for bottom left
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
TextWindow.WriteLine("hit")
EndIf
EndIf
endfor

EndSub
Sub stop

Shapes.Move(player, playerx, playery)
EndSub```

the object moves very smooth, but how can i make the player move smoother, and if the enemy can move faster while not compromising smoothness, that would be great.

Matthew

Friday, April 29, 2016 6:38 PM

• This is probably more of an answer than +litdev would approve of, but I'm remembering how much I would have liked the solution to a problem like this back in my early days.  :-)

Program.delay() is great when you need to pause a program. For frame pacing... not so much. The problem is that you perform the same delay regardless of how long it took to process the frame. Your program sets the frame rate at 60 times a -- optimistic for most games; very very optimistic for small basic. At the end of every frame you pause for 1000/60, or 16 milliseconds. Now imagine that it takes your game loop 15 milliseconds to process each frame. When you add the two together you end up with 15 * 60 + 16 * 50 or 1700 milliseconds of processing time you are trying to cram into each 1000 milliseconds of actual real time.

The trick for real time processing is to record a start time before the frame processing starts, and the have a pause loop that spins in place only for the amount of time remaining to complete the frame.

```'An example of a basic game loop, including exact frame pacing.
frameLength = 1000/60    'Number of milleseconds between animation frames
CreateShip()
GraphicsWindow.KeyDown = onKeyDown
GraphicsWindow.KeyUp = onKeyUp

'Game Loop --------------------
framestart = Clock.ElapsedMilliseconds          'Start the clock
While "True"
processKey()
moveShip()
frameDelay()                               'Wait a tick or two between moves
EndWhile

'Subroutines -------------------
Sub moveShip
Shapes.Move(ship, shipX, shipY)
EndSub

Sub CreateShip
shipX = GraphicsWindow.Width /2
shipY = GraphicsWindow.Height / 2
Shapes.Move(ship,shipX, shipY)
EndSub

Sub OnKeyDown
'Only process keys when they are down
pressed = "True"
EndSub

Sub OnKeyUp
'Stop process keys when none are pressed
pressed = "False"
EndSub

Sub ProcessKey
'process the keys once per frame
If pressed = "True" Then
key = GraphicsWindow.LastKey
If key = "Up" Then
shipY = shipY - 1
EndIf
EndIf
EndSub

Sub frameDelay
'Precise frame timing. More exact that program.delay() because it only
'pauses for the length of time remiaining in the current frame, rather than for the
'entire time slice of the frame. Even with longer, or shorter frame processing
'times, each fram will still be exactly frameLength in duration.
While Clock.ElapsedMilliseconds - framestart < frameLength
EndWhile
framestart = Clock.ElapsedMilliseconds
EndSub```

In addition to an example on frame pacing the above example also shows how to use the keyup and keydown events to manage the fact that GraphicsWindows.LastKey retains its current value forever, until changed.

Friday, April 29, 2016 7:58 PM

### All replies

• I think the issue is with the auto repeat delay on keys.

See here for ideas - you need a game loop and store the up and down state of keys rather than key presses.

Post back if need more help - I don't want to just post solution code.

Also any GW updates only happen AFTER event subs finish - hence do it all on main UI thread in game loop.
Friday, April 29, 2016 6:58 PM
• This is probably more of an answer than +litdev would approve of, but I'm remembering how much I would have liked the solution to a problem like this back in my early days.  :-)

Program.delay() is great when you need to pause a program. For frame pacing... not so much. The problem is that you perform the same delay regardless of how long it took to process the frame. Your program sets the frame rate at 60 times a -- optimistic for most games; very very optimistic for small basic. At the end of every frame you pause for 1000/60, or 16 milliseconds. Now imagine that it takes your game loop 15 milliseconds to process each frame. When you add the two together you end up with 15 * 60 + 16 * 50 or 1700 milliseconds of processing time you are trying to cram into each 1000 milliseconds of actual real time.

The trick for real time processing is to record a start time before the frame processing starts, and the have a pause loop that spins in place only for the amount of time remaining to complete the frame.

```'An example of a basic game loop, including exact frame pacing.
frameLength = 1000/60    'Number of milleseconds between animation frames
CreateShip()
GraphicsWindow.KeyDown = onKeyDown
GraphicsWindow.KeyUp = onKeyUp

'Game Loop --------------------
framestart = Clock.ElapsedMilliseconds          'Start the clock
While "True"
processKey()
moveShip()
frameDelay()                               'Wait a tick or two between moves
EndWhile

'Subroutines -------------------
Sub moveShip
Shapes.Move(ship, shipX, shipY)
EndSub

Sub CreateShip
shipX = GraphicsWindow.Width /2
shipY = GraphicsWindow.Height / 2
Shapes.Move(ship,shipX, shipY)
EndSub

Sub OnKeyDown
'Only process keys when they are down
pressed = "True"
EndSub

Sub OnKeyUp
'Stop process keys when none are pressed
pressed = "False"
EndSub

Sub ProcessKey
'process the keys once per frame
If pressed = "True" Then
key = GraphicsWindow.LastKey
If key = "Up" Then
shipY = shipY - 1
EndIf
EndIf
EndSub

Sub frameDelay
'Precise frame timing. More exact that program.delay() because it only
'pauses for the length of time remiaining in the current frame, rather than for the
'entire time slice of the frame. Even with longer, or shorter frame processing
'times, each fram will still be exactly frameLength in duration.
While Clock.ElapsedMilliseconds - framestart < frameLength
EndWhile
framestart = Clock.ElapsedMilliseconds
EndSub```

In addition to an example on frame pacing the above example also shows how to use the keyup and keydown events to manage the fact that GraphicsWindows.LastKey retains its current value forever, until changed.

Friday, April 29, 2016 7:58 PM
• thanks for this, this really really helps. I have never actually new how to do game loops, so this is a new way to think about it.

Matthew

Saturday, April 30, 2016 5:01 PM
• would you say the collision detector is decent? know any other way that could possibly be more effiecient?

Matthew

Saturday, April 30, 2016 5:03 PM
• In the collision_> is it possible to just have the enemy hit once, and only hurt the player once, not overlapping the damage. if the enemy touches the player, the first time they touch will hurt the player, but it wont continue to make the player lose health if they keep in contact with the enemy. I think my collision is wrongV
```Sub checkcollisionofplayer
healthloss = 2
py = Shapes.GetTop(player)
px = Shapes.GetLeft(player)
For i = 0 To numEnemy
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

'checks for top left
If ((ey >= py) and (ey <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
numhit = numhit + 1
losshealth = "True"
Else

EndIf
Else

EndIf
'checks for top right
If ((ey >= py) and (ey <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
numhit = numhit + 1
losshealth = "True"
Else

EndIf
Else

EndIf
'checks for bottom right
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
numhit = numhit + 1

losshealth = "True"
Else

EndIf
Else

EndIf
'checks for bottom left
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then

numhit = numhit + 1

losshealth = "True"
Else

EndIf
Else

EndIf
endfor
If losshealth = "True" Then
health = health - healthloss
endif
losshealth="False"
EndSub```

Matthew

Saturday, April 30, 2016 10:06 PM
• Hi Matthew,

to have the enemy hit once only after a collision, i found this :

if it detect a collision, something must happen:

1) go in the opposite direction,

or 2) create a new ship

or 3) anything else.....

in all cases we have to get out of the sub check collision routine, and go to and other routine that will issue new command to the new ship.

here i wrote a simple sub call something_happen were the ship that collides, is reset to 0, means new ship, and by the fact it rule the problem of many hits to 1.The reason why it end up with many hits, because after the first detection collision, you ship continue to move in those  ( 20 pixels ) and fill the fomula in your sub colllision check routine.

gh = 500
gw = 500
GraphicsWindow.Height=gh
GraphicsWindow.Width = gw
GraphicsWindow.CanResize = "False"
GraphicsWindow.KeyDown = move
GraphicsWindow.KeyUp = stop
frames = 60 ' really smooth
playerx = Math.GetRandomNumber(gh)
playery = Math.GetRandomNumber(gh)
pdX = 2
pdY= 2
Shapes.Move(player, playerx, playery)
numEnemy =1
For i = 0 to (numEnemy-1)
createenemy()

endfor
Sub createenemy
velX[i] = Math.GetRandomNumber(2)
velY[i] = Math.GetRandomNumber(2)

enemyx[i] = Math.GetRandomNumber(gh-15)
enemyy[i] = Math.GetRandomNumber(gh-15)

endsub

While 1=1
moveenemy()
checkcollisionofplayer()
Program.Delay((1000/frames))
endwhile

EndSub
Sub moveenemy
For i = 0 To numEnemy step 1 ' going through all the objects
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

If (ex >= gw-10) Or ( ex < 0) Then
velX[i] = velX[i] * -1
else
velX[i] = velX[i]
endif

If (ey >= gh - 10) Or ( ey < 0) Then
velY[i] = velY[i] * -1
Else
velY[i] = velY[i]

EndIf

enemyx[i] = enemyx[i]+ velX[i]
enemyy[i] = enemyy[i] + velY[i]
Shapes.Move(enemy[i], enemyx[i], enemyy[i])

endfor
endsub
Sub move
key = GraphicsWindow.LastKey
If (key = "A") then
pdX = -5
pdY=0
ElseIf (key = "D") then
pdX =5
pdY=0
elseif (key = "W") then
pdY = -5
pdX =0
elseif(key = "S") then
pdY =5
pdX =0
EndIf

If(Shapes.GetLeft(player) <0) or (Shapes.GetLeft(player) > (gw-15)) Then

If(Shapes.GetLeft(player) <0) Then
playerx = 0
ElseIf(Shapes.GetLeft(player) > (gw-15)) then
playerx = gw -15
EndIf
Else
playerx = playerx+pdX
EndIf
If((Shapes.Gettop(player) <0) or (Shapes.Gettop(player) > (gh-15))) Then

If(Shapes.Gettop(player) <0) Then
playery = 0
ElseIf(Shapes.Gettop(player) > (gh-15)) then
playery = (gh-15)
EndIf
Else
playery = playery + pdY
EndIf

Shapes.Move(player, playerx, playery)

EndSub
Sub checkcollisionofplayer

py = Shapes.GetTop(player)
px = Shapes.GetLeft(player)
For i = 0 To numEnemy
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

'checks for top left
If ((ey >= py) and (ey <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
TextWindow.WriteLine("hit")
something_happen()
EndIf
EndIf
'checks for top right
If ((ey >= py) and (ey <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
TextWindow.WriteLine("hit")
something_happen()
EndIf
EndIf
'checks for bottom right
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
TextWindow.WriteLine("hit")
something_happen()
EndIf
EndIf
'checks for bottom left
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
TextWindow.WriteLine("hit")
something_happen()
EndIf
EndIf
endfor

EndSub
Sub stop

Shapes.Move(player, playerx, playery)
EndSub

Sub something_happen
' we have a colllision or a hit
' somethin happen,
' 1) ship go in the opposite direction
' or
'2 ) new ship

enemyx[i]=0
enemyy[i]=0
EndSub

• Edited by Sunday, May 1, 2016 9:49 PM orthograph
Sunday, May 1, 2016 9:43 PM
• You have the basic idea of a hit bock down. Checking if the corners of one shape are inside the corners of another shape. The more complex the shape, the more comparisons you have to do. Here is a basic example for anyone else who may be following the thread:

Import Code: XTQ138

```'At the top of your program - Initial Setup
'Stuff up here only happens once before the main loop
GraphicsWindow.Show()
circleX = 0 'Starting place for the circle
circleY = Math.GetRandomNumber(GraphicsWindow.Height) 'Somewhere on the left side
cxDir = 1    'The direction the circle is moving --  1 = right and down, -1 = left and up
cyDir = 1

triangleX = GraphicsWindow.Width
triangleY = Math.GetRandomNumber(GraphicsWindow.Height) 'Somewhere on the right side
txDir = -1
tyDir = -1
frameRate = 5    'Number of milliseonds each frame (trip through the main program) should take
frameStart = Clock.ElapsedMilliseconds 'note the time to allow for frame pauses

'----------------------------------------------------------------------------

'Main Program Loop
'Repeats continuously until the escape key is pressed
key = ""
While GraphicsWindow.LastKey <> "Escape" 'Keep going until the escape key is pressed
MoveTheCircle()     'Update circle automatically
MoveTheTriangle()   'Update triangle Automatically
HitDetect()         'Chcck for collision between shapes - Nest If statments
'HitDetectShort()    'Chcck for collision between shapes - One compound if statement
FrameWait()         'Pause and wait for just a tick
endwhile

'----------------------------------------------------------------------------

'Subroutines.
'Always at the bottom of your program
'No code outside of a subroutine allowed below.

Sub MoveTheCircle
'called once during each trip through the loop, it moves the circle as needed.
GraphicsWindow.PenColor = "white"
GraphicsWindow.DrawRectangle(circleX,circleY,50,50)
circleX = circleX + cxDir
If circleX > GraphicsWindow.Width Or circleX < 0 Then 'If off the screen
cxDir = cxDir * -1  'reverse the direction
EndIf
circleY = circleY + cyDir
If circleY > GraphicsWindow.Height Or circleY < 0 Then 'If off the screen
cyDir = cyDir * -1  'reverse the direction
EndIf
Shapes.Move(circle,circleX,circleY)
GraphicsWindow.PenColor = "green"
GraphicsWindow.DrawRectangle(circleX,circleY,50,50)
EndSub

Sub MoveTheTriangle
'called once during each trip through the loop, it moves the triangle  as needed.
GraphicsWindow.PenColor = "white"
GraphicsWindow.DrawRectangle(triangleX,triangleY,50,50)
triangleX = triangleX + txDir
If triangleX > GraphicsWindow.Width Or triangleX < 0 Then 'If off the screen
txDir = txDir * -1  'reverse the direction
EndIf
triangleY = triangleY + tyDir
If triangleY > GraphicsWindow.Height Or triangleY < 0 Then 'If off the screen
tyDir = tyDir * -1  'reverse the direction
EndIf
Shapes.Move(triangle,triangleX,triangleY)
GraphicsWindow.PenColor = "green"
GraphicsWindow.DrawRectangle(triangleX,triangleY,50,50)
EndSub

Sub HitDetect
'Each object is represented by a single point inside of the compter. Its upper
'left corner. The object itself usually needs at least four points to describe
'its full location in two-dimensional space:
'Upper left = x,y
'Upper right = x + width, y
'Lower left = x, y + height
'Lower right = x + width, y + height
'       Side note -> you an make your hit boxes more complex. However the more points
'            you track, the more difficult the math will be, and the more time the comparison
'            will take. This is why most of the early 8-bit games stuck to rectangular
'            characters that filled a 16x16 pixel grid.

'To register a hit between the two objects, you have to check each of the four points
'to see they inside the other shape.

'Top left corner of circle inside of triangle?
'    First check to see if the X of the top right of the circle is inside the triangles hit box
'    Is the circles X more then the triangles X?  Is the circles X less than the triangles X plus the width of the triangle?
If circleX > triangleX And circleX < triangleX + 50 Then
'Next check to see if the Y of the top corner of the circle is inside the triangles hit box
'Is the circles Y more than the triangles Y? Is the circles Y less than the triangles Y plus the height of the triangle?
If circleY > triangleY And circleY < triangleY + 50 Then
ReactToHit()

'Bottom Left corner of circle inside of triangle?
'    Contine check -- since we already know x is in the right place, we can check the Y for the oppisite corner
'    Is the circles Y plus its height more than the triangles Y? Is the circles Y plus its height less than the triangles Y plus the height of the triangle?
ElseIf circleY + 50 > triangleY And circleY + 60 < triangleY + 50 Then
ReactToHit()
EndIf

'Top right corner of circle inside of triangle?
'    First check to see if the X of the top right of the circle is inside the triangles hit box
'    Is the circles X plus its width more then the triangles X?  Is the circles X plus its width less than the triangles X plus the width of the triangle?
ElseIf circleX+50 > triangleX And circleX + 50 < triangleX + 50 Then
'Next check to see if the Y of the top corner of the circle is inside the triangles hit box
'Is the circles Y more than the triangles Y? Is the circles Y less than the triangles Y plus the height of the triangle?
If circleY > triangleY And circleY < triangleY + 50 Then
ReactToHit()

'Bottom right corner of circle inside of triangle?
'    Contine check -- since we already know x is in the right place, we can check the Y for the oppisite corner
'    Is the circles Y plus its height more than the triangles Y? Is the circles Y plus its height less than the triangles Y plus the height of the triangle?
ElseIf circleY + 50 > triangleY And circleY + 60 < triangleY + 50 Then
ReactToHit()
EndIf
EndIf
EndSub

Sub HitDetectShort
'The giganitic nested if block above can be replaced with a single If statment
'if you put parenthesis ( ) around the and blocks and glue them together with or blocks:
If ((circleX > triangleX And circleX < triangleX + 50) And (circleY > triangleY And circleY < triangleY + 50)) Or ((circleX > triangleX And circleX < triangleX + 50) And (circleY + 50 > triangleY And circleY + 60 < triangleY + 50)) Or ((circleX+50 > triangleX And circleX + 50 < triangleX + 50) And (circleY > triangleY And circleY < triangleY + 50)) Or ((circleX+50 > triangleX And circleX + 50 < triangleX + 50) And (circleY + 50 > triangleY And circleY + 60 < triangleY + 50)) Then
ReactToHit()
EndIf
EndSub

sub ReactToHit
'When there is a hit, reverse the direction of both shapes.
cyDir = cyDir * -1
cxDir = cxDir * -1
tyDir = tyDir * -1
txDir = txDir * -1
EndSub

Sub FrameWait
While Clock.ElapsedMilliseconds - frameStart < frameRate
'Sit here and do nothing until the frame clock has run out.
'This wait keeps the automatic operations, like moving the ball
'from running too fast.
'This technique is better then using Program.Delay() for two reasons:
'   1)  The wait time is based on when we started the frame, not
'        when we ended it. In other words, when one of our trips through
'        the for loop above takes longer than normal, the delay will be
'        reduced, so each frame will be exactly the same length.
'  2) We have the option (even though we are not using it here) of
'        doing some extra processing, such as checking the keyboard.
'        With Program.Delay() we are stuck, unable to do anything,
'       until the  delay is complete.
EndWhile
frameStart = Clock.ElapsedMilliseconds 'Start  a new frame.
EndSub```

Monday, May 2, 2016 12:49 PM
• thats a good idea, but if i wanted the enemy to stay where it was at (relatively) could the enemy have a tracker saying that this enemy is already hit the player, hitpossible = false or something, and when the enemy isnt in collision anymore, it turns back to true?

Matthew

Monday, May 2, 2016 1:19 PM
• thanks for that answer... only issue that i see is that the triangle collision is a rectanlge, not a triangle, no biggie. But great answer, thanks for that, i actually never thought of that. Btw, guys here is the full code that i have so far. IT is runnable and you can leave it how it is, but im going to be making a smart enemy that follows the player-< Import XMG848 . thanks for all the help!!!

Matthew

Monday, May 2, 2016 1:23 PM
• If you want to do more than simply register a hit and move them apart again you will need to set some flags in the same way I set a flag in the key down example above. A variable that says that a hit has already taken place, but the two objects are still in contact:

```If (the two pieces are in the same place) Then
If (touching = "False") Then
'Process penalty for hit

'Track the fact that a hit is in action - no new hits while true
touching = "True"
EndIf
Else
'No longer touching, allow for new hits in the future
touching = "False"
EndIf```
After touching is set to "True" the game will no longer register a hit. This will keep the program from registering the fact over and over again the same single event. Once the two are apart, the flag is cleared and they can again react to each other.

Monday, May 2, 2016 1:40 PM
• i see, alright. I will try to incorperate this after i finish the smart enemy. Thanks for the help.

Matthew

Monday, May 2, 2016 1:42 PM
• Hi Matthew

Excellent so far !!!!!  your program XMG848

MY SCORE: 1850

can we choose our level ? say beginner, normal, expert , each level with a different speed ?

Monday, May 2, 2016 1:49 PM
• would this be the best way to get a shape to go in the direction of the player

```For i = 1 To snumEnemy
sex = Shapes.GetLeft(smartenemy[i])'SmartEnemyX
sey = Shapes.Gettop(smartenemy[i])

velX= (playerx-sex)/ math.Abs(playerx-sex) ' velocity will be 1 or -1 accordingly
vely= (playery-sey)/ math.Abs(playery-sey)```

Matthew

• Edited by Monday, May 2, 2016 1:51 PM typos
Monday, May 2, 2016 1:49 PM
• I have a theory on that, as the level gets higher, change the frame length (frames to higher than 60, that makes the game go faster.

my high score was around 4000, with 10 enemies. let me provide a screen shot.

Matthew

Monday, May 2, 2016 1:51 PM

• Matthew

Monday, May 2, 2016 1:56 PM
• very fun game, ! great reflex, mind perception, reaction skill !

here my new score: 2680

Monday, May 2, 2016 2:02 PM
• I'm looking forward to seeing how you will you take to program a smart ennemy ship.!!!  :)
Monday, May 2, 2016 2:06 PM
• it wont be that hard, i made this game is java already. im just testing it out on sb. are you having the player move on its own, where you just press the key and the player moves in that direction without you having to hold the key?

Matthew

Monday, May 2, 2016 2:11 PM
• my new score: 4760

Monday, May 2, 2016 2:15 PM
• I am trying to incorperate your method, but i cant get it to not hurt the player.

Look at collisionwithplayer (not the smartenemy one)

```gh = 400
gw = 400
GraphicsWindow.Height=gh
GraphicsWindow.Width = gw
GraphicsWindow.CanResize = "False"
init() ' initialize the saving

variables()' final variables that create the graphics window and all that.
GraphicsWindow.KeyDown = move ' key events that tell the player to move.
GraphicsWindow.KeyUp = stop ' nothing there
'if you want the player to stop when you let go of the key, go to this method and remove the ' on pressed="False"

framestart = Clock.ElapsedMilliseconds ' getsthe time
For i = 0 to 13 Step 1 'sets the level you are not on at false, refers to the enemy spawn
levelat[i] = "False"
endfor
smartenemyexists="False" ' refers to the smart enemy, not yet created in this program yet
numEnemy=1
createenemy()'initial enemy

'========GAME LOOP===========
While 1=1
ProcessKey() 'processes the key at the current frame
moveenemy() 'moves enemy
If(smartenemyexists) Then ' if we are starting to cook smartenenemies, then it will start to run the appropriate subroutine
movesmartenemy() ' nothing there, enemy will follow player around to prevent player from hiding in corners
EndIf
setlevel()'sets the level and updates it
checkcollisionofplayer() ' healthloss and collision
checkcollisionofplayersmartenemy()
updatehighscore() ' updates the highscore if score goes over it
adjusthealth() ' event to change number of health

enemyspawn() ' depending on level put an enemy, can be changed
framedelay()'frame delay
endwhile

Sub init
path = Program.Directory + "/Collision Game/"
name = "High Score"
ext = ".txt"

Shapes.Move(highscoredisplay, 0,50)
endsub

Sub variables
frames = 60
frameLength = 1000/frames  ' really smooth 0.016 millisecond frame. 1 frame every 0.016 millisecond.
'==============================
playerx = Math.GetRandomNumber(gh)
playery = Math.GetRandomNumber(gh)
Shapes.Move(player, playerx, playery)
'==============================

health = 100
GraphicsWindow.BrushColor= "Green"
Shapes.Move(healthdisplay, 0, 30)
'==============================
level = 1
Shapes.Move(leveldisplay, 350,0)
'==============================
GraphicsWindow.BrushColor= "BLue"
Shapes.Move(scoredisplay, 0, 0)
endsub
Sub createenemy
GraphicsWindow.BrushColor="Red"
vel = 1
'each enemy has its own id.
touching[numEnemy]="False"
velX[numEnemy] = vel'Math.GetRandomNumber(vel)
velY[numEnemy] = 0'Math.GetRandomNumber(vel)

enemyx[numEnemy] = Math.GetRandomNumber(gh-15)
enemyy[numEnemy] = Math.GetRandomNumber(gh-15)
endsub

Sub createsmartenemy
GraphicsWindow.BrushColor="Yellow"
smartenemyx[snumEnemy] = Math.GetRandomNumber(gh)
smartenemyy[snumEnemy] = Math.GetRandomNumber(gh)
touchings[snumEnemy] = "False"
vels = 2
EndSub

Sub ProcessKey
'process the keys once per frame
If pressed = "True" Then
key = GraphicsWindow.LastKey
If (key = "A") then
pdX = -1
pdY=0
ElseIf (key = "D") then
pdX =1
pdY=0
elseif (key = "W") then
pdY = -1
pdX =0
elseif(key = "S") then
pdY =1
pdX =0
EndIf
'===========this is the bounds check, makes sure the player doesnt leave the field.
If(Shapes.GetLeft(player) <0) or (Shapes.GetLeft(player) > (gw-15)) Then

If(Shapes.GetLeft(player) <0) Then
playerx = 0
ElseIf(Shapes.GetLeft(player) > (gw-15)) then
playerx = gw -15
EndIf
Else
playerx = playerx+pdX
EndIf
If((Shapes.Gettop(player) <0) or (Shapes.Gettop(player) > (gh-15))) Then

If(Shapes.Gettop(player) <0) Then
playery = 0
ElseIf(Shapes.Gettop(player) > (gh-15)) then
playery = (gh-15)
EndIf
Else
playery = playery + pdY
EndIf

Shapes.Move(player, playerx, playery)

EndIf
EndSub

Sub updatehighscore
If score > filesave[1] Then
filesave[1] = score
Shapes.SetText(highscoredisplay,  "Highest score: " +score)
endif
endsub

If ( health >0) Then
score = score +1
Else
GraphicsWindow.ShowMessage("You have lost, your score was " + score, "Game Over")
savescore()
Program.End()
EndIf
Shapes.SetText(scoredisplay, "Score: " +score)
EndSub

Shapes.SetText(healthdisplay,"Health: " + health)
endsub

Sub setlevel

If(score < 40) Then ' had issue where the level will jump once, so you will be already on level two.
Goto skip
endif
If(Math.Remainder(score, 200) = 0) then
level = level +1
EndIf
skip:
Shapes.SetText(leveldisplay,"Level: " +level)

endsub
Sub moveenemy
For i = 1 To (numEnemy) step 1 ' going through all the objects
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])
'===========simple collision================very rudamentary================
If (ex >= gw-10) Or ( ex < 0) Then
velX[i] = velX[i] * -1
else
velX[i] = velX[i]
endif

If (ey >= gh - 10) Or ( ey < 0) Then
velY[i] = velY[i] * -1
Else
velY[i] = velY[i]
EndIf

enemyx[i] = enemyx[i]+ velX[i]
enemyy[i] = enemyy[i] + velY[i]
Shapes.Move(enemy[i], enemyx[i], enemyy[i])

endfor
endsub

Sub enemyspawn

If(level<9) Then
If (levelat[level] ="False") Then
numEnemy=numEnemy+1
createenemy()
levelat[level]= "True"
endif

ElseIf(level>9) then
if (smartenemyexists="False") then
smartenemyexists="True"
If (levelat[level] ="False") Then

snumEnemy=snumEnemy+1
createsmartenemy()
levelat[level]= "True"
endif
EndIf
endif
endsub

Sub movesmartenemy
For i = 1 To snumEnemy
sex = Shapes.GetLeft(smartenemy[i])'SmartEnemyX
sey = Shapes.Gettop(smartenemy[i])
positionx = (playerx-sex)
positiony = (playery-sey)
If (positionx < 0) Then
velXS[i]= -vels
ElseIf (positionx>0) then
velXS[i] = vels
Else
velXS[i]=0
EndIf

If (positiony < 0) Then
velYS[i]= -vels
ElseIf (positiony>0) then
velYS[i] = vels
Else
velYS[i]=0
EndIf

smartenemyx[i] =smartenemyx[i] + velXS[i]
smartenemyy[i] =smartenemyy[i] + velYS[i]
Shapes.Move(smartenemy[i], smartenemyx[i], smartenemyy[i])

endfor
EndSub

Sub move
pressed = "True"

EndSub
Sub checkcollisionofplayersmartenemy
For i = 1 To snumEnemy
ey = Shapes.GetTop(smartenemy[i])
ex = Shapes.GetLeft(smartenemy[i])

'checks for top left
If(touchings[i]="False") Then
If ((ey >= py) and (ey <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
numhit = numhit + 1
losshealth = "True"
TextWindow.WriteLine("collision with " + i)
touching[i]="True"
Else

EndIf

Else
touchings[i]="False"

EndIf

'checks for top right
If ((ey >= py) and (ey <= (py+20))) Then
If (((ex+10) >= px) and ((ex+10) <= (px+20)))Then
numhit = numhit + 1
losshealth = "True"

touchings[i]="True"
Else
touching[i]="False"
EndIf
Else

EndIf
'checks for bottom right
If (((ey+10) >= py) and ((ey+10) <= (py+20))) Then
If (((ex+10) >= px) and ((ex+10) <= (px+20)))Then
numhit = numhit + 1

losshealth = "True"

touchings[i]="True"
Else
touchings[i]="False"
EndIf
Else

EndIf
'checks for bottom left
If (((ey+10) >= py) and ((ey+10) <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then

numhit = numhit + 1

losshealth = "True"
touchings[i]="True"
Else
touchings[i]="False"
EndIf
Else

EndIf

If losshealth = "True" Then
health = health - healthloss
endif
losshealth="False"
endif

endfor
endsub
'===========================================================================================
Sub checkcollisionofplayer
healthloss = 2
py = Shapes.GetTop(player)
px = Shapes.GetLeft(player)
For i = 1 To numEnemy
ey = Shapes.GetTop(enemy[i])
ex = Shapes.GetLeft(enemy[i])

'checks for top left

If ((ey >= py) and (ey <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
If(touching[i]="False") Then
health = health - healthloss
TextWindow.WriteLine("collision with " + i)
touching[i]="True"
Else

EndIf
Else
touching[i]="False"
EndIf

Else
EndIf

'checks for top right
If ((ey >= py) and (ey <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
If(touching[i]="False") Then
health = health - healthloss
TextWindow.WriteLine("collision with " + i)
touching[i]="True"
Else

EndIf
Else
touching[i]="False"
EndIf
Else
EndIf
'checks for bottom right
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If (((ex+15) >= px) and ((ex+15) <= (px+20)))Then
If(touching[i]="False") Then
health = health - healthloss
TextWindow.WriteLine("collision with " + i)
touching[i]="True"
Else

EndIf
Else
touching[i]="False"
EndIf

EndIf
'checks for bottom left
If (((ey+15) >= py) and ((ey+15) <= (py+20))) Then
If ((ex >= px) and (ex <= (px+20)))Then
If(touching[i]="False") Then
health = health - healthloss
TextWindow.WriteLine("collision with " + i)
touching[i]="True"
Else

EndIf
Else
touching[i]="False"
EndIf

EndIf
endfor
EndSub

Sub stop
'pressed="False"
'Shapes.Move(player, playerx, playery)

EndSub

Sub frameDelay'codingCat is the person to thank for this.

'Precise frame timing. More exact that program.delay() because it only
'pauses for the length of time remiaining in the current frame, rather than for the
'entire time slice of the frame. Even with longer, or shorter frame processing
'times, each fram will still be exactly frameLength in duration.
While Clock.ElapsedMilliseconds - framestart < frameLength ' if the time right now subtracted from the start time is les than frame length, then keep it.
'do nothing

EndWhile
framestart = Clock.ElapsedMilliseconds
EndSub

Sub savescore
path = Program.Directory + "/Collision Game/"
name = "High Score"
ext = ".txt"

If(score <= filesave[1]) Then 'if the score you got was less than your highscore,
'do not update the score, because that will become the score you got making the high score just a counter for the score you recently got.

Else
filesave[1] = score
endif
File.CreateDirectory(path)
File.WriteContents(path+name+ext, filesave)

endsub```

Matthew

Monday, May 2, 2016 3:00 PM
• Scratch that, i fixed it. Had to get each corner by itself. not as a whole.

here is the import since its really really long. -RTW739

i havent gotten to the smart enemy yet.

Yvan you should get higher this time.

Matthew

Monday, May 2, 2016 3:57 PM
• Alright, I finished the collision. I will work on adding a boss at the end of level 30 if you get there. and score will quadruple, but it will be hard as trying to catch a rice with chopsticks.(bruce lee reference)

here is the import-ZTD015

see how far you can get

Matthew

Monday, May 2, 2016 4:13 PM
• I Press those keys:

A to go left, D go right, S down, W up

if i press A , the ship go to the left without stopping, the only way to stop is to press the S key then move the ship to the right, but there must be a way to stop the ship if i don't press any key ?

What do you think of that ?

Monday, May 2, 2016 4:13 PM
• I did it that way so you can move faster, thats how i been able to get that high of a score. Test out the new game. import ztd015 i believe.

Matthew

Monday, May 2, 2016 4:15 PM
• Mathew,

i try your new version, i love the yellow ship following me everywhere !! wow !! that"s the smart ship isn't !

for the score, seems this time much easier, nice job !!!

that's the corner to corner detection i guess. it works!!!!

Monday, May 2, 2016 4:22 PM
• yes, thats because the velocity of the enemy doesnt go past 3. so its much slower. I was doing it at the speed where the enemy was at 8.5 velocity diagonal. much much faster. to change the speed of the enemy, go to createenemy and change vel to whatever number you want. can be a negative number.

my max score now is 2586, with velocity = to 6. the other time was where vel = 3.

Matthew

Monday, May 2, 2016 4:29 PM
• it's getting better and better !!!

here's my score this time with version ztd015

i've been trap by the yellow smart ship :)

2401

• Edited by Monday, May 2, 2016 7:39 PM smart ship
Monday, May 2, 2016 7:38 PM