Page 1 of 2

The Vampyres of Funnydale - PB 4.60 game

Posted: Sun Jan 08, 2012 9:52 pm
by BasicallyPure

Code: Select all

; *****************************
; VampyresOfFunnydale.pb      *
;                             *
; by BasicallyPure 01.14.2012 *
;                             *
; PureBasic 4.60              *
; *****************************

EnableExplicit

#Version = 102
#GameSpeed = 125 ; delay in mS between iterations

Declare Verify(result,text.s)

;gadgets
#Text_Vampyre   = 0
#Text_Human     = 1
#Font_Score     = 2
#Button_Pause   = 3
#Button_Skip    = 4
#Text_Level     = 5
#Button_Restart = 6
#Canvas         = 7
#Text_Waypoints = 8
#button_Help    = 9
#Editor         = 10

#yes = #PB_MessageRequester_Yes

#windowColor = $C3781A

ExamineDesktops()
Define winWidth = DesktopWidth(0) * 0.95
Define winHeight = winWidth * 0.5625

Define text$ = "Vampyres of Funnydale v" + StrF(#Version/100,2)
Define flags = #PB_Window_ScreenCentered | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
Verify(OpenWindow(0, 0, 0, winWidth, winHeight, text$ , flags),"OpenWindow 0")

SetWindowColor(0,#windowColor)
AddWindowTimer(0,0,#GameSpeed)

;define the cell colors
Define human    = $59A457
Define vampyer  = $0DF4F2
Define slayer   = $2517DA
Define empty    = $042452
Define waypoint = $FF0000

Frame3DGadget(#PB_Any, 10, 10, 100, 45, "Humans")
Frame3DGadget(#PB_Any, 10, 60, 100, 45, "Vampyres")
Frame3DGadget(#PB_Any, 10, 110, 100, 45, "Level")
Frame3DGadget(#PB_Any, 10, 160, 100, 45, "Waypoints")

LoadFont(#Font_Score, "Courier New", 14, #PB_Font_Bold)
SetGadgetFont(#PB_Default,FontID(#Font_Score))

flags = #PB_Text_Right
TextGadget(#Text_Human, 15, 25, 85, 28, "0" , flags)
SetGadgetColor(#Text_Human, #PB_Gadget_BackColor, #windowColor)

TextGadget(#Text_Vampyre, 15, 75, 85, 28, "0" ,flags)
SetGadgetColor(#Text_Vampyre, #PB_Gadget_BackColor, #windowColor)

TextGadget(#Text_Level, 15, 125, 85, 28, "" ,flags)
SetGadgetColor(#Text_Level, #PB_Gadget_BackColor, #windowColor)

TextGadget(#Text_Waypoints, 15, 175, 85,28, "0", flags)
SetGadgetColor(#Text_Waypoints, #PB_Gadget_BackColor, #windowColor)

ButtonGadget(#button_Help, 10, 230, 100, 35, "Read Me")
GadgetToolTip(#button_Help, "Game description")

ButtonGadget(#Button_Restart, 10, 280, 100, 35, "Restart")
GadgetToolTip(#Button_Restart, "Repeat this level")

ButtonGadget(#Button_Skip, 10, 330, 100, 35, "Level up")
GadgetToolTip(#Button_Skip, "Go to next level")

ButtonGadget(#Button_Pause, 10, 380, 100, 35, "Slay")
GadgetToolTip(#Button_Pause, "Activate the Slayer")

Macro drawCell(x,y)
   Box(cell(x,y)\Xloc, cell(x,y)\Yloc, cellSize, cellSize, cell(x,y)\content)
EndMacro

Macro ask(text)
   answer = MessageRequester("", text ,#PB_MessageRequester_YesNo)
EndMacro

Define cellSize, columns, rows, width, height, event, humanCount, vampyreCount
Define x, y, n, nx, ny, sx, sy, rc, pixels, target, xOffset
Define flags, trendX, trendY, burst, direction, howfarX, howfarY
Define updatePopulation, wp, wpa, wpx, wpy, wpCost, wpMax, waypointFlag
Define scanRange, nextLevel, answer, evolve, pause = #True
Define.f aspectFactor
Define d$

Structure stats
   Xloc.i
   Yloc.i
   content.i
EndStructure

Define level = 1

Repeat ;- game loop
   ;{ reconfigure screen for each level
   width = winWidth - 130 ; make room for gadgets
   height = winHeight
   pixels = width * height
   aspectFactor = width / height
   wpCost = 6 * level ;the cost of waypoints in vampyres slain
   wpMax = 15 * wpCost ;set the maximum number of waypoints
   
   SetGadgetText(#Text_Level,Str(level) + " of 9")
   
   ;set vampyre detection range, should be 'odd' number
   scanRange = level * 2 + 1
   
   target = level * 700 + 700 ; construct the game area with about this many cells
   columns = Round(Sqr(target * aspectFactor), #PB_Round_Nearest)
   rows = Round(Sqr(target / aspectFactor), #PB_Round_Nearest)
   
   cellSize = height / rows
   
   ;readjust width & height to exact values
   width = cellSize * columns
   height = cellSize * rows
   
   ;number of random cells chosen for each iteration
   burst = target / 30
   
   ;compensate for array's elements starting at zero
   columns - 1
   rows - 1
   
   cellSize - 1 ;this is for 1 pixel border around each cell
   waypointFlag = #False
   trendX = 2 * Random(1) - 1 ;set trendX -1 or +1
   trendY = 2 * Random(1) - 1 ;set trendY -1 or +1
   
   xOffset = winWidth - width
   
   If IsGadget(#Canvas)
      ResizeGadget(#Canvas,xOffset, 0, width, height)
   Else
      Verify(CanvasGadget(#Canvas, xOffset, 0, width, height),"CanvasGadget")
   EndIf
   
   StartDrawing(CanvasOutput(#Canvas))
   Box(0,0,width,height,0) ;paint it black
   StopDrawing()
   
   Dim cell.stats(columns, rows)
   
   ;- populate the world
   ;{ define the content of each cell
   nx = 0 : ny = 0
   ;calculate & store the x y corner pixel location of each world cell
   ;start with all cells empty
   For y = 1 To height - cellSize
      For x = 1 To width - cellSize
         With cell(nx,ny)
         \Xloc = x : \Yloc = y : \content = empty
         EndWith
         x + cellSize : nx + 1
      Next x
      y + cellSize : ny + 1 : nx = 0
   Next y
   
   ;define the starting population
   humanCount = (columns * rows) / 50
   vampyreCount = (columns * rows) / 50
   SetGadgetText(#Text_Human,Str(humanCount))
   SetGadgetText(#Text_Vampyre,Str(vampyreCount))
   
   With cell(x,y)
      ;distribute the human population
      For n = 1 To humanCount
         Repeat ; find an empty cell
            x = Random(columns) : y = Random(rows)
         Until \content = empty
         \content = human
      Next n
     
      ;distribute the vampyre population
      For n = 1 To vampyreCount
         Repeat ; find an empty cell
            x = Random(columns) : y = Random(rows)
         Until \content = empty
         \content = vampyer
      Next n
   
      Repeat ; make the Slayer cell
         x = Random(columns) : y = Random(rows)
      Until \content = empty
      \content = slayer
      rc = empty : sx = x : sy = y
   EndWith

   ; draw all cells
   If StartDrawing(CanvasOutput(#Canvas))
      For y = 0 To rows
         For x = 0 To columns
            drawCell(x,y) ;macro
         Next x
      Next y
      StopDrawing()
   EndIf
   
   Repeat ; level loop
      evolve = #False
      Repeat ;-event loop
         Event = WindowEvent()
         Select Event
            Case #PB_Event_CloseWindow
               ask("Confirm end program?")
               If answer = #yes
                  End
               EndIf
            Case #PB_Event_Gadget
               Select EventGadget()
                  Case #Canvas
                     Select EventType()
                        Case #PB_EventType_LeftButtonDown
                           If wpa ; check for available waypoints
                              x = GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)
                              y = GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)
                           
                              Verify(StartDrawing(CanvasOutput(#Canvas)),"StartDrawing")
                              wp - wpCost
                              wpa = wp / wpCost
                              If waypointFlag
                                 drawCell(wpx,wpy) ;macro
                              EndIf
                              wpx = x / (cellSize+1)
                              wpy = y / (cellSize+1)
                              waypointFlag = #True
                              Box(cell(wpx,wpy)\Xloc, cell(wpx,wpy)\Yloc, cellSize, cellSize, waypoint)
                              StopDrawing()
                              trendX = 2 * Random(1) - 1 ;set trendX -1 or +1
                              trendY = 2 * Random(1) - 1 ;set trendY -1 or +1
                           EndIf
                     EndSelect
                  Case #Button_Pause ;toggle pause
                     pause ! #True
                     If pause
                        SetGadgetText(#Button_Pause,"Slay")
                        GadgetToolTip(#Button_Pause, "Activate the Slayer")
                     Else
                        SetGadgetText(#Button_Pause,"Pause")
                        GadgetToolTip(#Button_Pause, "Freeze the game")
                     EndIf
                  Case #Button_Skip
                     ask("skip to next level?")
                     If answer = #yes
                        nextLevel = #True : pause = #False
                     EndIf
                  Case #Button_Restart
                     ask("Restart this level?")
                     If answer = #yes
                        level - 1 : nextLevel = #True : pause = #False
                     EndIf
                  Case #button_Help
                     flags = #PB_Window_ScreenCentered | #PB_Window_SystemMenu
                     text$ = "Vampyres of Funnydale - Message -"
                     Verify(OpenWindow(1,0,0,WindowWidth(0)-50,WindowHeight(0)-50,text$,flags),"openWindow 1")
                     StickyWindow(1,1)
                     EditorGadget(#Editor, 0,0,WindowWidth(1),WindowHeight(1),#PB_Editor_ReadOnly)
                     SetGadgetColor(#Editor, #PB_Gadget_BackColor, $99FFFF)
                     text$ = ""
                     
                     Restore message
                     Read.s d$
                     While d$ <> "EndMessage"
                        text$ + d$ + #CRLF$
                        Read.s d$
                     Wend
                     
                     SetGadgetText(#Editor,text$)
                     
                     Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
                     
                     CloseWindow(1)
                     UseGadgetList(WindowID(0))
               EndSelect
            Case #PB_Event_Timer
               If EventTimer() = 0
                  evolve = #True
               EndIf
         EndSelect
         If pause : Delay(10) : EndIf
      Until (Not Event) And (Not pause) And evolve
      ;} end event loop
     
      ;{ evolve all cells
      If StartDrawing(CanvasOutput(#Canvas))
         For n = 1 To burst
            x = Random(columns) : y = Random(rows)
            If cell(x,y)\content <> empty
               nx = Random(2) - 1
               If x + nx < 0 Or x + nx > columns : nx = 0 : EndIf
               ny = Random(2) - 1
               If y + ny < 0 Or y + ny > rows : ny = 0 : EndIf
               If nx <> 0 Or ny <> 0
                  nx + x : ny + y
                  Select cell(x,y)\content
                     Case human
                        If cell(nx,ny)\content = empty ;spawn human
                           cell(nx,ny)\content = human
                           humanCount + 1
                           drawCell(nx,ny) ;macro
                        ElseIf cell(nx,ny)\content = human ;kill human
                           cell(x,y)\content = empty
                           humanCount - 1
                           drawCell(x,y) ;macro
                        EndIf
                     Case vampyer
                        If cell(nx,ny)\content = empty ;move vampyer
                           cell(x,y)\content = empty
                           drawCell(x,y) ;macro
                           cell(nx,ny)\content = vampyer
                           drawCell(nx,ny) ;macro
                        ElseIf cell(nx,ny)\content = human ;turn human into vampyre
                           cell(nx,ny)\content = vampyer
                           drawCell(nx,ny) ;macro
                           humanCount  - 1 : vampyreCount + 1
                        EndIf
                  EndSelect
               EndIf
            EndIf
         Next n
         
         ; move the slayer
         If waypointFlag ;move toward waypoint
            nx = Sign(wpx - sx)
            ny = Sign(wpy - sy)
            If sx + nx = wpx And sy + ny = wpy
               waypointFlag = #False
            EndIf
         Else ; move normal
            x = sx : y = sy ;point to the slayer square
            direction = 2 * Random(1) - 1 ; choose -1 or +1
            howfarX = 1 : howfarY = 1
            Repeat ;this loop runs only once by design
               Repeat ;begin scanning for vampyres
                  For n = 1 To howfarX
                     x + direction
                     If  x >= 0 And x <= columns ; in bounds
                        If cell(x,y)\content = vampyer
                           nx = Sign(x - sx) : ny = Sign(y - sy)
                           Break 3 ;scan finished
                        EndIf
                     Else ; out of bounds
                        x - direction : howfarX - 1
                        Break
                     EndIf
                  Next n
                  For n = 1 To howfarY
                     y + direction
                     If y >= 0 And y <= rows ; in bounds
                        If cell(x,y)\content = vampyer
                           nx = Sign(x - sx) : ny = Sign(y - sy)
                           Break 3 ; scan finished
                        EndIf
                     Else ; out of bounds
                        y - direction : howfarY -1
                        Break
                     EndIf
                  Next n
                  howfarX + 1 : howfarY + 1 : direction * -1
               Until howfarX > scanRange Or howfarY > scanRange
               
               ;no vampyres in scan range so move by trend
               If Random(100) < 4 ;change trend before moving
                  trendX = Random(2) - 1
                  If trendX <> 0
                     trendY = Random(2) - 1
                  Else
                     trendY = 2 * Random(1) - 1
                  EndIf
               EndIf
               nx = trendX : ny = trendY
               ; prevent out of bounds movement
               If sx + nx < 0 Or sx + nx > columns
                  nx * -1 : trendX * -1
               EndIf
               If sy + ny < 0 Or sy + ny > rows
                  ny * -1 : trendY * -1
               EndIf
            Until #True ;this loop never repeats
         EndIf ; End move the slayer
         
         With cell(sx,sy)
            Select rc ; restore previous human or kill vampyre
               Case human ; restore the previous human cell
                  \content = human
               Case vampyer ; kill the vampyre cell
                  \content = empty
                  vampyreCount - 1
                  If wp < wpMax : wp + 1 : EndIf
                  wpa = wp / wpCost
               Default
                  \content = empty
            EndSelect
            drawCell(sx,sy) ;macro
           
            sx + nx : sy + ny ; update slayer coordinates
            rc = \content ; remember what the cell content was
            \content = slayer
            drawCell(sx,sy) ;macro
         EndWith
     
         StopDrawing()
      EndIf
     
      updatePopulation + 1
      If updatePopulation = 10
         updatePopulation = 0
         SetGadgetText(#Text_Human,Str(humanCount))
         SetGadgetText(#Text_Vampyre,Str(vampyreCount))
         SetGadgetText(#Text_Waypoints,Str(wpa))
         If  Not vampyreCount
            If level < 9
               Delay(1000)
               text$ = "level " + Str(level) + " complete!"
               text$ + #CRLF$ + "continue?"
               ask(text$)
               If answer = #yes
                  nextLevel = #True
               Else
                  End
               EndIf
            Else
               nextLevel = #True
            EndIf
         EndIf
         If Not humanCount
            MessageRequester("Game Over"," You Lose! ")
            End
         EndIf
      EndIf
      ;}
     
   Until nextLevel
   
   nextLevel = #False
   pause = #True
   SetGadgetText(#Button_Pause,"Slay")
   GadgetToolTip(#Button_Pause, "Activate the Slayer")
   wp = 0
   SetGadgetText(#Text_Waypoints,Str(wp))
   level + 1
   If level = 9
      DisableGadget(#Button_Skip, #True)
   EndIf
Until level = 10

MessageRequester("","Congratulations!" + #CRLF$ + "You have won!")

End

Procedure Verify(result,text.s)
   If result = #False
      text +  " failed To initialize."
      MessageRequester("Error!",text)
      End
   EndIf
   ProcedureReturn result
EndProcedure

DataSection
   message:
   Data.s "Welcome to Funnydale."
   Data.s #CRLF$
   Data.s "Funnydale is a town with a problem, it seems the town is infested with vampyres."
   Data.s "The humans (green squares) are being turned into vampyres (yellow squares)."
   Data.s "Fortunately for the humans they have a protector, a 'Vampyre Slayer' (red square)."
   Data.s "You Robert Miles, are here To help the Slayer exterminate the vampyres from Funnydale."
   Data.s "The Vampyre Slayer does quite well alone but with your guidance can be even more effective."
   Data.s "Your only way To help is to use the mouse to set 'waypoint' markers to guide the slayer."
   Data.s "When waypoints become available you click on a cell and the Slayer will move to that cell."
   Data.s ""
   Data.s "Like all humans the people of Funnydale multiply if left alone."
   Data.s "Because they are mortal they also sometimes die of natural causes."
   Data.s "Vampyres can only increase their numbers by turning a human into a vampyre."
   Data.s "Vampyres are immortal, only the Slayer can destroy a vampyre."
   Data.s ""
   Data.s "The game consists of nine different levels, each level more difficult than the one before."
   Data.s "To complete a level you must destroy all of the vampyres on that level."
   Data.s "If all of the humans are eliminated on any level the game will end."
   Data.s "To win the game you must complete all levels."
   Data.s ""
   Data.s "Close this window to continue."
   Data.s "EndMessage"
EndDataSection
Edit: Added confirmation to 'close window'.
Edit2: Fixed waypoint bug.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sun Jan 08, 2012 10:22 pm
by Bisonte
Nice Game !

Waypoints without killing vampyres will be a nice feature ;)
Sometimes the slayer moves "around" the vampires and then he/she dont kill one, so...
you know what I mean ?

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sun Jan 08, 2012 11:41 pm
by idle
cool game got to level 7

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Mon Jan 09, 2012 12:00 am
by BasicallyPure
I was testing level 9 just to see if it could be done.
I had been going for about 20 minutes and things were looking pretty good.
Then I accidentally clicked the close window button by mistake.
Dohh!!

I think I could have won though.

I'm going to add confirmation to the close window. :mrgreen:

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Mon Jan 09, 2012 2:27 pm
by Demivec
BasicallyPure wrote:I was testing level 9 just to see if it could be done.
I had been going for about 20 minutes and things were looking pretty good.
Then I accidentally clicked the close window button by mistake.
Dohh!!

I think I could have won though.
Great game. Here's my winning screenshot:
Image

I confess that it took longer than 20 minutes. :D

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Fri Jan 13, 2012 9:30 pm
by Nituvious
There is a bug in your code that allows you to have infinite number of waypoints. If you have 2 waypoint and click around a few times and let the slayer reach the point, then you will go below 0 and can have an infinite amount of them.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sat Jan 14, 2012 12:41 am
by J. Baker
Nice game! Still testing it out. Compiles and plays on Mac! :D

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sat Jan 14, 2012 1:42 am
by J. Baker
Your game got me somewhat creative, so I made you an icon for your game. Well, a png image anyway. Of course you don't have to use it, I just did it for fun. ;)
Image

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sat Jan 14, 2012 4:04 am
by Demivec
Nituvious wrote:There is a bug in your code that allows you to have infinite number of waypoints. If you have 2 waypoint and click around a few times and let the slayer reach the point, then you will go below 0 and can have an infinite amount of them.
I wish I would have discovered that bug. I unfortunately discovered a related bug not so nice bug. Your waypoint's count can overflow when it reaches a maximum and be reset to zero.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sat Jan 14, 2012 7:29 am
by BasicallyPure
Nituvious wrote:There is a bug in your code that allows you to have infinite number of waypoints. If you have 2 waypoint and click around a few times and let the slayer reach the point, then you will go below 0 and can have an infinite amount of them.
OK, I was able to verify the bug.
It should be fixed now.

Demivec wrote:I wish I would have discovered that bug. I unfortunately discovered a related bug not so nice bug. Your waypoint's count can overflow when it reaches a maximum and be reset to zero.
Can you describe how to recreate that bug?
I don't know where to start looking for that one.

@ J. Baker
Thanks for the icon, it is nice. :)

B. P.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sat Jan 14, 2012 5:21 pm
by Demivec
BasicallyPure wrote:
Demivec wrote:I wish I would have discovered that bug. I unfortunately discovered a related bug not so nice bug. Your waypoint's count can overflow when it reaches a maximum and be reset to zero.
Can you describe how to recreate that bug?
I don't know where to start looking for that one.
I've tried to recreate the bug but have been unsuccessful. I also can't see how it would occur from the code. Instead of it being a bug I think I may have simply clicked repeatedly on a single cell and in the process used up all of my waypoints before the screen updated to show that I was out of waypoints. I would reclassify this as being a not-bug. :)

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Sun Apr 08, 2012 9:57 pm
by Jago
Awesome game! Have you thought about adding some graphics?

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Tue Apr 10, 2012 5:10 am
by BasicallyPure
Thanks, I'm glad you liked it.

I thought about adding graphics but I didn't come up with any good ideas.
Anyone is welcome to try if they want to.

B.P.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Tue Apr 10, 2012 6:51 pm
by Zach
Really neat game, I had fun and got to level 4 before I quit to do some other stuff.

I think it would be kind of hard to come up with suitable graphics for the game, just based on the way it is visually presented.

Re: The Vampyres of Funnydale - PB 4.60 game

Posted: Wed Apr 11, 2012 11:51 pm
by Kuron
Interesting little gem of a game.

I think it would be kind of hard to come up with suitable graphics for the game, just based on the way it is visually presented.
I have a couple of ideas.