Yksinkertainen puzzle peli toteutettuna Hollywoodilla, jossa ohjataan Kiinanpalatsikoira Apia ja yritetään kerätä kaikki pelikentällä olevat luut. Tikapuiden avulla pääsee liikkumaan ylä -ja alasuunnassa, kiviä voi työnnellä ja hiekan näköisen peliruudun voi "kaivaa" sivusuunnassa.
Peliprojekti: http://xob.kapsi.fi/~ljl/peli/apisrc.zip
Valmiiksi käännettynä: http://xob.kapsi.fi/~ljl/peli/apiWin32.zip
@APPICON {Ic16x16 = "my16x16icon.png", Ic24x24 = "my24x24icon.png", Ic32x32 = "my32x32icon.png", Ic48x48 = "my48x48icon.png", Ic128x128 = "my128x128icon.png", Ic256x256 = "my256x256icon.png", Ic512x512 = "my512x512icon.png"} ;UI constants Const #UI_PANEL_HEIGHT = 25 Const #TILESIZE = 49 ;Level map dimensions Const #COLUMNS = 11 Const #ROWS = 8 ; Some constanst to help identify map tiles and brushes Const #EMPTY = 0 Const #WALL = 1 Const #LADDER = 2 Const #WALL2 = 3 Const #ROCK = 4 Const #BONE = 5 Const #PLAYER = 6 Const #LEFT_ARROW_BUTTON = 7 Const #RIGHT_ARROW_BUTTON = 8 Const #SMILEY_BUTTON = 9 Const #APIPLEFT = 10 Const #APIPRIGHT = 11 Const #TITLE = 12 Const #TITLE_TEXT = 13 Const #PRESS_SPACE_TEXT = 14 Const #LEVEL_DONE_TEXT = 15 @DISPLAY {Width = #COLUMNS * #TILESIZE, Height = #ROWS * #TILESIZE + #UI_PANEL_HEIGHT, Title = "Api's Adventure"} @BRUSH #WALL, "wall.png", {LoadAlpha = True} @BRUSH #LADDER, "ladder.png", {LoadAlpha = True} @BRUSH #WALL2, "wall2.png", {LoadAlpha = True} @BRUSH #ROCK, "rock.png", {LoadAlpha = True} @BRUSH #BONE, "bone.png", {LoadAlpha = True} @BRUSH #PLAYER, "api.png", {LoadAlpha = True} @BRUSH #LEFT_ARROW_BUTTON, "left.png", {LoadAlpha = True} @BRUSH #RIGHT_ARROW_BUTTON, "right.png", {LoadAlpha = True} @BRUSH #SMILEY_BUTTON, "smiley.png", {LoadAlpha = True} @BRUSH #APIPLEFT, "apil.png", {LoadAlpha = True} @BRUSH #APIPRIGHT, "apir.png", {LoadAlpha = True} @BRUSH #TITLE, "title.png" @BRUSH #TITLE_TEXT, "titlet.png", {LoadAlpha = True} @BRUSH #PRESS_SPACE_TEXT, "pspace.png", {LoadAlpha = True} @BRUSH #LEVEL_DONE_TEXT, "donet.png", {LoadAlpha = True} ; Create Brush for empty map tile CreateBrush(#EMPTY, #TILESIZE, #TILESIZE, #GRAY) Function DrawUI() SetFillStyle(#FILLCOLOR) Box(0, 0, 49 * 11, 25, #WHITE) DisplayBrush(#LEFT_ARROW_BUTTON, 2, 2) DisplayBrush(#RIGHT_ARROW_BUTTON, 22, 2) DisplayBrush(#SMILEY_BUTTON, 11 * 47, 2) SetFont(#TRUETYPE_DEFAULT, 20) SetFontColor(#BLACK) TextOut(50, 2, "level: " .. clevel + 1, #BLACK) EndFunction ; Create level table with methods from the global levels table index n Function InitLevel(n) Local level = {} level.map = CopyTable(levels[n].map) Function level:DrawMap() For Local j = 0 To #ROWS - 1 For Local i = 0 To #COLUMNS - 1 DisplayBrush(self.map[i][j], i * #TILESIZE, j * #TILESIZE + #UI_PANEL_HEIGHT) Next Next EndFunction level.player = { x = levels[n].player.x, y = levels[n].player.y } Function level:DrawPlayer() DisplayBrush(#PLAYER, self.player.x * #TILESIZE, self.player.y * #TILESIZE + #UI_PANEL_HEIGHT) EndFunction Function level:PlayerFall() If self.map[self.player.x][self.player.y] <> #EMPTY Then Return Local y = self.player.y For Local i = y + 1 To #ROWS - 1 Local found, id, pos = self:SearchObjects(self.player.x, i) If self.map[self.player.x][i] <> #EMPTY Or found Then Break y = i Next self.player.y = y EndFunction level.objects = {} level.nobjs = levels[n].nobjs level.nbones = levels[n].nbones For Local i = 0 To levels[n].nobjs - 1 level.objects[i] = {id = levels[n].objects[i].id, x = levels[n].objects[i].x, y = levels[n].objects[i].y} Next Function level:DrawObjects() For Local i = 0 To level.nobjs - 1 DisplayBrush(self.objects[i].id, self.objects[i].x * #TILESIZE, self.objects[i].y * #TILESIZE + #UI_PANEL_HEIGHT) Next EndFunction Function level:SearchObjects(x, y) If self.nobjs < 1 Then Return(False, 0, i) For Local i = 0 To self.nobjs - 1 If self.objects[i].x = x And self.objects[i].y = y Then Return(True, self.objects[i].id, i) Next Return(False, 0, i) EndFunction Function level:ObjectsFall() If self.nobjs < 1 Then Return For Local j = 0 To self.nobjs - 1 Local y = self.objects[j].y For Local i = y + 1 To #ROWS - 1 Local found, id, pos = self:SearchObjects(self.objects[j].x, i) If self.map[self.objects[j].x][i] <> #EMPTY Or found Or self.objects[j].x = self.player.x And i = self.player.y Then Break y = i Next self.objects[j].y = y Next EndFunction Function level:SortObjects() Sort(self.objects, Function(a, b) Return(a.y > b.y) EndFunction) EndFunction Function level:Draw() self:DrawMap() self:DrawObjects() self:DrawPlayer() EndFunction Return(level) EndFunction ; Level parser, loads levels into global levels table Function LoadLevels(fid, fname) nlevels = 0 Local Line = 1 Local x = 0 Local y = 0 Local o = 0 Local b = 0 levels = {} levels[nlevels] = {} levels[nlevels].player = {x = 0, y = 0} Dim map[11][8] levels[nlevels].map = CopyTable(map) map = Nil levels[nlevels].objects = {} OpenFile(fid, fname) While Eof(fid) = False Local c = ReadChr(fid) Switch c Case ';' While c <> '\n' And Eof(fid) = False Do c = ReadChr(fid) Line = Line + 1 Case '\n': y = y + 1 If x <> 11 DebugPrint("Level parser error on line:", Line, "column:", x, "Level map must have", #COLUMNS, "columns") End EndIf Line = Line + 1 x = 0 If Eof(fid) = False Then c = ReadChr(fid) If c = '\n' Or Eof(fid) = True If y <> 8 DebugPrint("Level parser error on line:", Line, "Levels must be separated with one line feed and level map must have:", #ROWS, "rows") End EndIf levels[nlevels].nobjs = o levels[nlevels].nbones = b nlevels = nlevels + 1 y = 0 o = 0 b = 0 If Eof(fid) = False Line = Line + 1 levels[nlevels] = {} levels[nlevels].player = {x = 0, y = 0} Dim map[11][8] levels[nlevels].map = CopyTable(map) map = Nil levels[nlevels].objects = {} EndIf Else Seek(fid, FilePos(fid) - 1) EndIf Case '0': levels[nlevels].map[x][y] = #EMPTY x = x + 1 Case '1': levels[nlevels].map[x][y] = #WALL x = x + 1 Case '2': levels[nlevels].map[x][y] = #LADDER x = x + 1 Case '3': levels[nlevels].map[x][y] = #WALL2 x = x + 1 Case 'b': levels[nlevels].objects[o] = {id = #BONE, x = x, y = y} b = b + 1 o = o + 1 x = x + 1 Case '@': levels[nlevels].player = {x = x, y = y} x = x + 1 Case 'o': levels[nlevels].objects[o] = {id = #ROCK, x = x, y = y} o = o + 1 x = x + 1 Default: DebugPrint("Level parser error: impossible character", Chr(c), "on line:", Line, "column:", x) End EndSwitch Wend EndFunction Function p_HandlerFunc(msg) Switch msg.action Case "OnKeyDown": Switch msg.key Case "UP": Local ny = level.player.y - 1 If ny >= #ROWS Or ny < 0 Then Break Local found = level:SearchObjects(level.player.x, ny) If found Then Break; If level.map[level.player.x][level.player.y] = #LADDER And level.map[level.player.x][ny] = #LADDER Or level.map[level.player.x][level.player.y] = #LADDER And level.map[level.player.x][ny] = #EMPTY level.player.y = ny level:PlayerFall() level:Draw() Flip() StartTimer(1) WaitTimer(1, 100) EndIf Case "DOWN": Local ny = level.player.y + 1 If ny >= #ROWS Or ny < 0 Then Break Local found = level:SearchObjects(level.player.x, ny) If found Then Break; If level.map[level.player.x][ny] = #LADDER Or level.map[level.player.x][level.player.y] = #LADDER And level.map[level.player.x][ny] = #EMPTY level.player.y = ny level:PlayerFall() level:ObjectsFall() level:Draw() Flip() StartTimer(1) WaitTimer(1, 100) EndIf Case "LEFT": Local nx = level.player.x - 1 If nx >= #COLUMNS Or nx < 0 Then Break If level.map[nx][level.player.y] <> #WALL Local found, id, index = level:SearchObjects(nx, level.player.y) If found <> False Switch id Case #ROCK: level:DrawMap() level:DrawObjects() DisplayBrush(#APIPLEFT, level.player.x * #TILESIZE, level.player.y * #TILESIZE + #UI_PANEL_HEIGHT) Flip() StartTimer(1) WaitTimer(1, 100) Local nrx = level.objects[index].x - 1 If nrx < #COLUMNS And nrx >= 0 found = level:SearchObjects(nrx, level.player.y) If found = False And level.map[nrx][level.player.y] = #EMPTY level.objects[index].x = nrx level.player.x = nx level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() Return EndIf EndIf Case #BONE: RemoveItem(level.objects, index) level.nobjs = level.nobjs - 1 level.nbones = level.nbones - 1 level.player.x = nx EndSwitch Else If level.map[nx][level.player.y] = #WALL2 Then level.map[nx][level.player.y] = #EMPTY level.player.x = nx EndIf level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() StartTimer(1) WaitTimer(1, 100) EndIf Case "RIGHT": Local nx = level.player.x + 1 If nx >= #COLUMNS Or nx < 0 Then Break If level.map[nx][level.player.y] <> #WALL Local found, id, index = level:SearchObjects(nx, level.player.y) If found <> False Switch id Case #ROCK: level:DrawMap() level:DrawObjects() DisplayBrush(#APIPRIGHT, level.player.x * #TILESIZE, level.player.y * #TILESIZE + #UI_PANEL_HEIGHT) Flip() StartTimer(1) WaitTimer(1, 100) Local nrx = level.objects[index].x + 1 If nrx < #COLUMNS And nrx >= 0 found = level:SearchObjects(nrx, level.player.y) If found = False And level.map[nrx][level.player.y] = #EMPTY level.objects[index].x = nrx level.player.x = nx level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() Return EndIf EndIf Case #BONE: RemoveItem(level.objects, index) level.nobjs = level.nobjs - 1 level.nbones = level.nbones - 1 level.player.x = nx EndSwitch Else If level.map[nx][level.player.y] = #WALL2 Then level.map[nx][level.player.y] = #EMPTY level.player.x = nx EndIf level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() StartTimer(1) WaitTimer(1, 100) EndIf EndSwitch EndSwitch If level.nbones < 1 clevel = clevel + 1 clevel = Wrap(clevel, 0, nlevels) level = InitLevel(clevel) DisplayBrush(#LEVEL_DONE_TEXT, #CENTER, #CENTER) Flip() StartTimer(1) WaitTimer(1, 1000) DrawUI() level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() EndIf EndFunction Function p_ButtonHandler(msg) Switch msg.action Case "OnMouseUp": Switch msg.id Case 1: clevel = clevel - 1 clevel = Wrap(clevel, 0, nlevels) level = InitLevel(clevel) DrawUI() level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() Case 2: clevel = clevel + 1 clevel = Wrap(clevel, 0, nlevels) level = InitLevel(clevel) DrawUI() level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() Case 3: level = InitLevel(clevel) DrawUI() level:SortObjects() level:PlayerFall() level:ObjectsFall() level:Draw() Flip() EndSwitch Case "OnMouseOver": ; Nothing yet, but maybe one could darken UI buttons to highlight them. EndSwitch EndFunction evtmatch = {OnMouseUp = p_ButtonHandler, OnMouseOver = p_ButtonHandler} MakeButton(1, #SIMPLEBUTTON, 2, 2, 20, 20, evtmatch) MakeButton(2, #SIMPLEBUTTON, 22, 2, 20, 20, evtmatch) MakeButton(3, #SIMPLEBUTTON, 11 * 47, 2, 20, 20, evtmatch) LoadLevels(1, "levels.txt") ; Current level clevel = 0 level = InitLevel(clevel) DisplayBrush(#TITLE, #CENTER, #CENTER) DisplayBrushFX(#TITLE_TEXT,#CENTER, #CENTER, {Type = #ZOOMCENTER}) DisplayBrushFX(#PRESS_SPACE_TEXT, #CENTER, #BOTTOM, {Type = #VSTRETCHCENTER}) WaitKeyDown("SPACE") BeginDoubleBuffer() level:SortObjects() DrawUI() level:Draw() Flip() InstallEventHandler({OnKeyDown = p_HandlerFunc}) SetEventTimeout(50) Repeat WaitEvent Forever
Aihe on jo aika vanha, joten et voi enää vastata siihen.