Balloons - a Scratch tutorial written in Hollywood

The place for any Hollywood tutorials
User avatar
emeck
Posts: 169
Joined: Fri Apr 03, 2015 3:17 pm

Balloons - a Scratch tutorial written in Hollywood

Post by emeck »

Hello,

I found a nice Scratch tutorial of a simple game and decided to make a Hollywood version. It has helped me to understand how to use sprites. I post the code here but you can get the srcipt and all other files from here in case you are interested in trying it. Please, if you have any suggestions or improvements share them so we all can learn.

Finally, thanks to jPV for suggestions, corrections and bug hunting!

Code: Select all

@APPTITLE "Balloons"
@APPAUTHOR "Enrique Mecklenburg"
@APPVERSION "$VER: Balloons 1.1 (08-Oct-19)"
@APPDESCRIPTION "Scratch example written in Hollywood"


/*********************************
*  Objective of the game is to   *
*  click on the balloons to pop  *
*  them before time ends.        *
*********************************/

@DISPLAY 1, {Width = 640, Height = 480}

@BGPIC 2, "background.png"

;balloon sprites, each with 2 frames, one with the
;balloon image and one with the popped image
@BRUSH 1, "balloon_blue.png", {LoadAlpha = True}
@BRUSH 2, "balloon_black.png", {LoadAlpha = True}
@BRUSH 3, "balloon_green.png", {LoadAlpha = True}
@BRUSH 4, "balloon_red.png", {LoadAlpha = True}

@SAMPLE 1, "pop.8svx"

EscapeQuit(True)

SetFillStyle(#FILLCOLOR)

balloons = 15          ;total ballons on screen
time = 10              ;total time in seconds
countdown = {}         ;table for storing time numbers
score = 0              ;starting score
scores = {}            ;table for storing score numbers
done = False           ;is game over?


/******************
 * Balloon object *
 ******************/
balloon = {}           ;prototype table for balloon objects

;constructor for new balloon object
Function balloon:new()    
    ;create sprite from random brush, width and height, load 2 frames and it has 2 frames per row
    o = {sprite = CreateSprite(Nil, #BRUSH, Rnd(4) + 1, 54, 70, 2, 2),
         x = 5 + Rnd(575),                          ;set balloon's initial horizontal coord
		 y = 30 + Rnd(345),                         ;set balloon's initial vertical coord
		 sx = -3 + Rnd(7),                          ;set balloon's horizontal speed
		 sy = -3 + Rnd(7),                          ;set balloon's horizontal speed
         notPopped = True}                          ;created balloon is not popped yet
    SetMetaTable(o, {__index = balloon})            ;set balloon as the "prototype" for new balloon objects
    Return(o)
EndFunction

;move balloon object
Function balloon:move()
    If self.notPopped
        ;set new position
        self.x = self.x + self.sx
        self.y = self.y + self.sy

        ;check horizontal and vertical limits
        If self.x > 586 Or self.x < 0 Then self.sx = -self.sx
	    If self.y > 410 Or self.y < 25 Then self.sy = -self.sy

        ;display sprite's frame 1 in new position
        DisplaySprite(self.sprite, self.x, self.y, 1)
    EndIf
EndFunction

;pop balloon object when hit
Function balloon:pop()
    self.notPopped = False                          ;balloon now popped
    DisplaySprite(self.sprite, self.x, self.y, 2)   ;display popped frame
    PlaySample(1)                                   ;play pop sound
    Wait(1)
    RemoveSprite(self.sprite)                       ;remove balloon sprite
EndFunction

/*** End balloon object ***/




/*******************
 * Create balloons *
 *******************/
Function p_CreateBalloons()
    For Local i = 1 To balloons
        balloon[i] = balloon:new()                  ;create new balloon object
    Next
EndFunction


/********************************************
 * Create scores and display starting score *
 ********************************************/
Function p_CreateScore()
    scoreText = CreateTextObject(Nil, "Score: ")                        ;create "Score" text

    For Local i = 0 To balloons
	    CreateTextObject(1, PadNum(i, 2))                               ;create numbers for score as text objects
	    scores[i] = CreateSprite(Nil, #TEXTOBJECT, 1)                   ;convert numbers to sprites
        FreeTextObject(1)		                                        ;free memory of no longer deeded text objects
    Next

    DisplayTextObject(scoreText, 10, 4)                                 ;display "Score" text
    DisplaySprite(scores[score], 70, 4)                                 ;display starting score
EndFunction


/**********************
 * Create time sprite *
 **********************/
Function p_CreateCountdown()
    timeText = CreateTextObject(Nil, "Time: ")                          ;create "Time" text

    For Local i = 0 To time
        CreateTextObject(1, PadNum(time - i, 2))                        ;create timer numbers as text objects starting at 10
        countdown[i] = CreateSprite(Nil, #TEXTOBJECT, 1)                ;convert numbers to sprites
        FreeTextObject(1)
    Next

    For Local i = 0 To time
        CreateTextObject(i, PadNum(time - i, 2))                        ;create timer numbers as text objects starting at 10
    Next

    DisplayTextObject(timeText, 550, 4)                                 ;display "Time" text
    DisplaySprite(countdown[0], 600, 4)                                 ;display starting time
EndFunction


/*****************
 * Move balloons *
 *****************/
Function p_MoveBalloons()
    BeginRefresh()
    For Local i = 1 To balloons
        balloon[i]:move()                                               ;move balloon object
    Next
    EndRefresh()
EndFunction


/***************************
 * Check if balloon is hit *
 ***************************/
Function p_Burst()
    Local mx, my = MouseX(), MouseY()		                            ;store mouse position when clicked

    For Local i = balloons To 1 Step -1                                 ;negative step so click works on balloon "on top" in case of overlapping with other
        If balloon[i].notPopped
            Local bx, by = balloon[i].x, balloon[i].y                   ;copy balloon position

            ;check if balloon sprite was hit
	        If mx > bx And mx < bx + 54 And my > by And my < by + 70
	            balloon[i]:pop()                                        ;remove popped balloon
                RemoveSprite(scores[score])
                score = score + 1
	            DisplaySprite(scores[score], 70, 5)                     ;update score: shows next frame of scores sprite
	            If score = balloons
		            p_GameOver()
	            EndIf
	            Break
            EndIf
        EndIf
    Next
EndFunction


/************************
 * Check time countdown *
 ************************/
Function p_Countdown()
    ;remember that time sprites run from 10 to 0
    Local t = Int(GetTimer(1) / 1000)       ;get next second

    ;when resuming after a pause, the display is redrawn and the time sprite is not in sync with the timer
    ;this checks for the sprite displayed when pausing and removes it before the next is displayed
    If t > 0
        If GetAttribute(#SPRITE, countdown[t-1], #ATTRONSCREEN) Then RemoveSprite(countdown[t-1])
    EndIf
    
    If t => time
	    DisplaySprite(countdown[t], 600, 4) ;display last time sprite (countdown[10]) which is 0
	    p_GameOver("lose")
    Else
        DisplaySprite(countdown[t], 600, 4) ;display next time sprite
    EndIf
EndFunction


/*************
 * Game over *
 *************/
Function p_GameOver(endText$)
    StopTimer(1)
    ClearInterval(2)
    ClearInterval(1)

    done = True             ;game is over

    RemoveSprites(True)     ;remove sprites but keep graphics displayed so box can be draw on top

    Box(0, 0, 640, 480, Color = #GRAY, {Transparency = "50%"})

    SetFont(#SANS, 36, {Engine = #FONTENGINE_INBUILT})
    SetFontStyle(#BOLD)
    SetFontStyle(#ANTIALIAS)

    If endText$ = "lose"
	    TextOut(#CENTER, #CENTER, "Game Over")
    Else
	    TextOut(#CENTER, #CENTER, "You won!")
    EndIf

    Wait(100)
    TextOut(#CENTER, 260, "Play again? Y/N")
EndFunction


/************
 * Clean up *
 ************/
Function p_CleanUp()
    For Local i = 0 To balloons
	    FreeSprite(scores[i])             ;free sprites created for score
    Next

    For Local i = 0 To time
	    FreeSprite(countdown[i])           ;free sprites created for timer
    Next

    For Local i = 1 To balloons
	    FreeSprite(balloon[i].sprite)     ;free sprites created for balloons
    Next

    FreeTextObject(scoreText)             ;free text objects
    FreeTextObject(timeText)

    score = 0
EndFunction


/*****************
 * Main function *
 *****************/
Function p_Start()
    done = False          ; game is not over

    SetFont(#SANS, 18, {Engine = #FONTENGINE_INBUILT})
    SetFontStyle(#BOLD)
    SetFontStyle(#ANTIALIAS)

    DisplayTransitionFX(2, {Type = #FADE, Speed = 50, Parameter = #WHITE})	;display background with a transition fx

    Box(0, 0, 640, 25, #GRAY, {Transparency = "50%"})          ;score and time area

    p_CreateScore()                                            ;set starting score
    p_CreateCountdown()                                        ;set remaining time
    Wait(25)
    p_CreateBalloons()                                         ;create and show balloons

    StartTimer(1)                                              ;start timer

    SetInterval(1, p_Countdown, 1000)                          ;execute timecountdown loop, 1 second interval
    SetInterval(2, p_MoveBalloons, 1000/25)                    ;execute main loop at 25fps
EndFunction


/***********************************
 * Check mouse and keyboard events *
 ***********************************/
Function p_EventFunction(msg)
    Switch(msg.action)
    Case "OnMouseDown":
	    If done = False
	        p_Burst()                                          ;check if balloon is hit
	    EndIf
    Case "OnKeyDown":
	    If msg.key = " " And HaveObject(#TIMER, 1)	           ;check if SPACE pressed and timer 1 is running
	        PauseTimer(1)				                       ;pause timer
	        WaitKeyDown("Space")                               ;pause the script until SPACE is pressed again
	        ResumeTimer(1)
	    ElseIf (msg.key = "Y" Or msg.key = "y") And done       ;restart if game over
	        p_CleanUp()
	        p_Start()
	    ElseIf (msg.key = "N" Or msg.key = "n") And done       ;quit if game over
	        End()
	    EndIf
    EndSwitch
EndFunction


InstallEventHandler({OnMouseDown = p_EventFunction, OnKeyDown = p_EventFunction})

p_Start()    ;start game

Repeat
    WaitEvent()
Forever
PowerBook 5.2 MorphOS 3.15
PowerBook 5.8 MorphOS 3.15
Amiga 1200 BPPC/BVision AOS4.1 FE
SantiDarkG
Posts: 11
Joined: Wed Jun 05, 2019 10:47 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by SantiDarkG »

Thanks Emeck...... I will take a look. Is always awesome when somebody posted a small tutorial for newbies like me :)
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by Juan Carlos »

Hi, I downloaded your source example, and I have one suggestion, you can make the game for kids, shot to the balloons, change the mouse pointer for a peephole, add highscore list, different points for balloons color, etc.
User avatar
emeck
Posts: 169
Joined: Fri Apr 03, 2015 3:17 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by emeck »

@SantiDarkG
Glad you like it. I'm also learning HW and this kind of small challenges help me to learn new skills. While I was using this to play with sprites I also learnt a little about objects with LUA and HW.

I hope to share more like this.
PowerBook 5.2 MorphOS 3.15
PowerBook 5.8 MorphOS 3.15
Amiga 1200 BPPC/BVision AOS4.1 FE
User avatar
emeck
Posts: 169
Joined: Fri Apr 03, 2015 3:17 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by emeck »

@Juan Carlos
Juan Carlos wrote: Tue Oct 15, 2019 1:31 pm ...different points for balloons color, etc.
I like that idea. Not much time available right now but I'll keep that in mind. Maybe others can improve the code meanwhile.
PowerBook 5.2 MorphOS 3.15
PowerBook 5.8 MorphOS 3.15
Amiga 1200 BPPC/BVision AOS4.1 FE
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by Juan Carlos »

The idea is very easy and it won't take you long, other thing is you want make a game with professional purposes, and the 75% of programming already you done, and your example is a good idea to make a game for kids, without violence.
LarsB
Posts: 72
Joined: Sat May 06, 2017 4:37 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by LarsB »

Cute! Thank you.
User avatar
lazi
Posts: 625
Joined: Thu Feb 24, 2011 11:08 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by lazi »

Juan Carlos wrote: Wed Oct 16, 2019 12:48 pm the 75% of programming already you done,
They say that the final 10% of the job takes the 90% of the whole development time. :)
https://en.wikipedia.org/wiki/Ninety-ninety_rule
User avatar
emeck
Posts: 169
Joined: Fri Apr 03, 2015 3:17 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by emeck »

@lazi

Yes! I have made some changes in the code (still trying and learning new stuff) and implemented some new things to release it as a simple game as suggested by Juan Carlos.

But I have been busy lately so, "two more weeks".
PowerBook 5.2 MorphOS 3.15
PowerBook 5.8 MorphOS 3.15
Amiga 1200 BPPC/BVision AOS4.1 FE
User avatar
emeck
Posts: 169
Joined: Fri Apr 03, 2015 3:17 pm

Re: Balloons - a Scratch tutorial written in Hollywood

Post by emeck »

But I have been busy lately so, "two more weeks".
So, after a veeeeeeeeeeeeeeery long two more weeks, FIRST PUBLIC RELEASE!

Seriously, during Christmas time I got back to Hollywood and this project. And the last couple of weeks I have been catching bugs. In the end I have a working game with:

- Start menu
- Player's name
- Highscores
- Localisation

Some screenshots:
Image
Image
Image

You can download the code and binaries from github here: https://github.com/emeck/hw_balloons/releases/tag/v2.0

I only tested MorphOS, Linux and Windows binaries.

It has been fun and a good learning experience. Changed Cubic IDE for FlowStudio which is very nice once you get used to it. Learned the basics of git and created the repos on both gitlab and bitbucket; but I will continue using github which seems easier for making releases. And for compiling I use Allanon's APPBuilder which makes very easy to compile your project to several targets.

So, I have some other little games I want to try before 2 big projects in store.
PowerBook 5.2 MorphOS 3.15
PowerBook 5.8 MorphOS 3.15
Amiga 1200 BPPC/BVision AOS4.1 FE
Post Reply