Block- Man Script

The place for any Hollywood tutorials
ocean77
Posts: 111
Joined: Mon Jan 28, 2019 8:34 pm

Block- Man Script

Post by ocean77 »

Simple script to make a block move around a 800x600 window using the arrow keys.
(Extracted and modified from the "Simple Break-Out Clone" script by: ArtBlink & Figgy/CtZ & amyren, found elsewhere on this forum)

Code: Select all

@DISPLAY{WIDTH = 800, HEIGHT = 600, MODE = "WINDOWED"} ;Create the window

CreateBrush(1,32,32,#GREEN)  ; CREATE BLOCK-MAN

BM_Xpos = #CENTER ; Set initial X-position
BM_Ypos = #CENTER ; Set initial Y-position
SPEED = 5 ; Set the movement speed

Function p_UpdateScreen()
    
    ;Check Key-presses and move Block-Man:
    If IsKeyDown("LEFT") = True Then BM_XPos = BM_XPos - SPEED
    If IsKeyDown("RIGHT") = True Then BM_XPos = BM_XPos + SPEED
    If IsKeyDown("UP") = True Then BM_YPos = BM_YPos - SPEED
    If IsKeyDown("DOWN") = True Then BM_Ypos = BM_Ypos + SPEED
    
    ;Check if Block-Man leaves the screen and reposition if he does:
    If BM_XPos < 0 Then BM_XPos = 0
	If BM_XPos > 768 Then BM_XPos = 768
    If BM_Ypos < 0 Then BM_Ypos = 0
    If BM_Ypos > 568 Then BM_Ypos = 568

    DisplayBrush(1, BM_Xpos, BM_Ypos)
	
EndFunction

BeginDoubleBuffer()
EscapeQuit(True)
Repeat
	Cls()
	p_UpdateScreen()
	Flip()
Forever
EndDoubleBuffer()
Two issue: How can I use the initial position without it being instantly updated before any key is pressed?
How can I avoid the speed increase when moving diagonally?
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: Block- Man Script

Post by jPV »

3rd issue: This is a prime example of a bad (very very bad!) code mentioned here in the Hollywood documentation:
https://www.hollywood-mal.com/docs/html ... ming_.html

The program runs in a so called "busy loop" without waits, which is very bad coding practise (you can't emphasize this enough). It makes your computer run unnecessary hot, waste electricity, and leaves less CPU time for other programs in your system. So please read the documentation how to code main loops properly, and I hope the original example wasn't doing it like this or if it was, hopefully it hasn't been copied too many times :)

Sorry a bit hurry to reply to the actual questions now... but just had to tell this :)
ocean77
Posts: 111
Joined: Mon Jan 28, 2019 8:34 pm

Re: Block- Man Script

Post by ocean77 »

jPV wrote: Sat Dec 10, 2022 8:45 pm 3rd issue: This is a prime example of a bad (very very bad!) code mentioned here in the Hollywood documentation:
https://www.hollywood-mal.com/docs/html ... ming_.html

The program runs in a so called "busy loop" without waits, which is very bad coding practise (you can't emphasize this enough). It makes your computer run unnecessary hot, waste electricity, and leaves less CPU time for other programs in your system. So please read the documentation how to code main loops properly, and I hope the original example wasn't doing it like this or if it was, hopefully it hasn't been copied too many times :)

Sorry a bit hurry to reply to the actual questions now... but just had to tell this :)
Thanks for letting me know. I don't think that was discussed in the original thread. Will update the original post with a warning.
How might this be rectfied? Sorry, I am still very much a beginner and this was meant for like-minded folk. ;)

EDIT: I actually can't edit the original post. WARNING! Don't do this, guys. It's BAD practice. :lol:
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: Block- Man Script

Post by jPV »

Argh, sorry, I was actually wrong with this, now when looking the code with better time, Flip() without argument defaults to True and actually waits for a screen refresh and you don't need to sync to a certain framerate after all. So it doesn't loop wildly. It would do that if you'd give False for it...

So nothing wrong unless you want to make it run in a specific framerate. But maybe this was a good reminder for not doing it wrong ;)

Too bad I can't edit my original post either! :D
ocean77
Posts: 111
Joined: Mon Jan 28, 2019 8:34 pm

Re: Block- Man Script

Post by ocean77 »

No worries.
Think I got it... So even though it defaults to 'True', saying: Flip(True) is better for readability(?)
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: Block- Man Script

Post by jPV »

ocean77 wrote: Sun Dec 11, 2022 1:11 pm So even though it defaults to 'True', saying: Flip(True) is better for readability(?)
Yeah, I think so, because usually if you don't give any arguments to a function, it defaults to Nil/False...
Flinx
Posts: 188
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: Block- Man Script

Post by Flinx »

To the second issue:
You have to use the speed as a vector and split it into x- and y-parts. This is quite simple here, because the box moves only in an angle of 45°, so the horizontal and vertical parts are equal. I made a quick hack with your code:

Code: Select all

@DISPLAY{WIDTH = 800, HEIGHT = 600, MODE = "WINDOWED"} ;Create the window

CreateBrush(1,32,32,#GREEN)  ; CREATE BLOCK-MAN

BM_Xpos = #CENTER ; Set initial X-position
BM_Ypos = #CENTER ; Set initial Y-position
SPEED = 5 ; Set the movement speed
SPEED45=Sqrt(SPEED^2/2)
/*
speed as vector, Pythagoras:
SPEEDX^2+SPEEDY^2 =      SPEED^2
SPEEDX^2          =      SPEED^2-SPEEDY^2
SPEEDX            = Sqrt(SPEED^2-SPEEDY^2)
SPEEDY            = Sqrt(SPEED^2-SPEEDX^2)
*/

Function p_UpdateScreen()
    
    ;Check Key-presses and move Block-Man:
    ;SPEEDX=Sqrt(SPEED^2/2)
    SPEEDX=SPEED45 ; calculate this only one time
    SPEEDY=SPEEDX ; (because 45°)
    If Not IsKeyDown("LEFT") And Not IsKeyDown("RIGHT")
	SPEEDX=0
	SPEEDY=SPEED
    EndIf    
    If Not IsKeyDown("UP") And Not IsKeyDown("DOWN")
        SPEEDY=0
	SPEEDX=SPEED
    EndIf 

    If IsKeyDown("LEFT") = True Then BM_XPos = BM_XPos - SPEEDX
    If IsKeyDown("RIGHT") = True Then BM_XPos = BM_XPos + SPEEDX
    If IsKeyDown("UP") = True Then BM_YPos = BM_YPos - SPEEDY
    If IsKeyDown("DOWN") = True Then BM_Ypos = BM_Ypos + SPEEDY
    
    ;Check if Block-Man leaves the screen and reposition if he does:
    If BM_XPos < 0 Then BM_XPos = 0
	If BM_XPos > 768 Then BM_XPos = 768
    If BM_Ypos < 0 Then BM_Ypos = 0
    If BM_Ypos > 568 Then BM_Ypos = 568

    DisplayBrush(1, BM_Xpos, BM_Ypos)
	
EndFunction

BeginDoubleBuffer()
EscapeQuit(True)
Repeat
	Cls()
	p_UpdateScreen()
	Flip()
Forever
EndDoubleBuffer()
ocean77
Posts: 111
Joined: Mon Jan 28, 2019 8:34 pm

Re: Block- Man Script

Post by ocean77 »

Flinx wrote: Wed Dec 14, 2022 12:36 pm To the second issue:
You have to use the speed as a vector and split it into x- and y-parts. This is quite simple here, because the box moves only in an angle of 45°, so the horizontal and vertical parts are equal. I made a quick hack with your code:
Brilliant! Thanks! :)
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: Block- Man Script

Post by Juan Carlos »

Good example, this may be the beginning of Pong game.
ocean77
Posts: 111
Joined: Mon Jan 28, 2019 8:34 pm

Re: Block- Man Script

Post by ocean77 »

So, I am trying to add some elements to this script. Namely adding a obstacle in the form of a 32x32 pixel square.

I am using the following code:

Code: Select all

if Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos =< BL_Xpos
        BM_XPos, BM_YPos = BL_XPos - 16, BM_YPos ; Handle collision with left side of obstacle
        DebugPrint("Hit The Left Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos =< BL_Xpos + 32
        BM_XPos, BM_YPos = BL_XPos + 32, BM_YPos ; Handle collision with right side of obstacle
        DebugPrint("Hit The Right Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Ypos >= BL_Ypos
        BM_XPos, BM_YPos = BM_XPos, BL_YPos + 32 ; Handle collision with bottom side of obstacle
        DebugPrint("Hit The Bottom Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos >= BL_Xpos
        BM_XPos, BM_YPos = BM_XPos, BL_YPos - 16 ; Handle collision with top side of obstacle
        DebugPrint("Hit The Top Side")
    EndIf
However, only two of these conditions work at a time and I am too dumb to figure out why. In fact I spent several hours trying to get any of the condition to work. Any input would be welcome.

The complete script in its current form:

Code: Select all

@DISPLAY{WIDTH = 800, HEIGHT = 600, MODE = "WINDOWED"} ;Create the window

CreateBrush(1, 16, 16, #GREEN)  ; CREATE BLOCK-MAN
CreateBrush(2, 32, 32, #GRAY)   ; CREATE OBSTICLE

BM_Xpos = #CENTER ; Set initial X-position
BM_Ypos = #CENTER ; Set initial Y-position
SPEED = 3 ; Set the movement speed
SPEED45=Sqrt(SPEED^2/2)

BL_Xpos = 400 ; Obstacle position
BL_Ypos = 300

/*
speed as vector, Pythagoras:
SPEEDX^2+SPEEDY^2 =      SPEED^2
SPEEDX^2          =      SPEED^2-SPEEDY^2
SPEEDX            = Sqrt(SPEED^2-SPEEDY^2)
SPEEDY            = Sqrt(SPEED^2-SPEEDX^2)
*/

Function p_UpdateScreen()
    
    ;Check Key-presses and move Block-Man:
    ;SPEEDX=Sqrt(SPEED^2/2)
    SPEEDX=SPEED45 ; calculate this only one time
    SPEEDY=SPEEDX ; (because 45°)
    
    If Not IsKeyDown("LEFT") And Not IsKeyDown("RIGHT")
	    SPEEDX=0
	    SPEEDY=SPEED
    EndIf    
    
    If Not IsKeyDown("UP") And Not IsKeyDown("DOWN")
        SPEEDY=0
	    SPEEDX=SPEED
    EndIf 

    If IsKeyDown("LEFT") = True Then BM_XPos = BM_XPos - SPEEDX
    If IsKeyDown("RIGHT") = True Then BM_XPos = BM_XPos + SPEEDX
    If IsKeyDown("UP") = True Then BM_YPos = BM_YPos - SPEEDY
    If IsKeyDown("DOWN") = True Then BM_Ypos = BM_Ypos + SPEEDY
    
    ;Check if Block-Man leaves the screen and reposition if he does:
    If BM_XPos < 0 Then BM_XPos = 0
	If BM_XPos > 784 Then BM_XPos = 784
    If BM_Ypos < 0 Then BM_Ypos = 0
    If BM_Ypos > 584 Then BM_Ypos = 584

    ;Check if we're colliding with obstacle:
   
    ; Can only get two of these conditions to work:
    
    if Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos =< BL_Xpos
        BM_XPos, BM_YPos = BL_XPos - 16, BM_YPos ; Handle collision with left side of obstacle
        DebugPrint("Hit The Left Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos =< BL_Xpos + 32
        BM_XPos, BM_YPos = BL_XPos + 32, BM_YPos ; Handle collision with right side of obstacle
        DebugPrint("Hit The Right Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Ypos >= BL_Ypos
        BM_XPos, BM_YPos = BM_XPos, BL_YPos + 32 ; Handle collision with bottom side of obstacle
        DebugPrint("Hit The Bottom Side")

    elseif Collision(#BRUSH, 1, BM_XPos, BM_YPos, 2, BL_Xpos, BL_Ypos ) = True and BM_Xpos >= BL_Xpos
        BM_XPos, BM_YPos = BM_XPos, BL_YPos - 16 ; Handle collision with top side of obstacle
        DebugPrint("Hit The Top Side")
    EndIf

    ;Display our elements at their respective positions:
    DisplayBrush(1, BM_Xpos, BM_Ypos)
	DisplayBrush(2, BL_XPos, BL_Ypos)
EndFunction

BeginDoubleBuffer()
EscapeQuit(True)
Repeat
	Cls()
	p_UpdateScreen()
	Flip()
Forever
EndDoubleBuffer()
Post Reply