├── README.md └── diablo.p8 /README.md: -------------------------------------------------------------------------------- 1 | # pico8-diablo 2 | A Diablo I clone for Pico-8 3 | -------------------------------------------------------------------------------- /diablo.p8: -------------------------------------------------------------------------------- 1 | pico-8 cartridge // http://www.pico-8.com 2 | version 41 3 | __lua__ 4 | -- entity 5 | 6 | entity = {} 7 | entity.__index = entity 8 | 9 | function entity:init(x, y, sprite) 10 | local self = setmetatable({}, entity) 11 | self.x = x or 0 12 | self.y = y or 0 13 | self.speed = 1 14 | self.sprite = sprite or 0 15 | self.health = 0 16 | self.is_dead = false 17 | return self 18 | end 19 | 20 | function entity:draw() 21 | if not self.is_dead then 22 | spr(self.sprite, self.x, self.y) 23 | end 24 | end 25 | 26 | function entity:update() 27 | self:check_death() 28 | end 29 | 30 | function entity:check_death() 31 | if self.health <= 0 then 32 | self.is_dead = true 33 | end 34 | end 35 | 36 | 37 | direction = { 38 | left = 0, 39 | right = 1, 40 | down = 2, 41 | up = 3, 42 | } 43 | 44 | function entity:move(d) 45 | if d == direction.left then 46 | self.x -= self.speed 47 | elseif d == direction.right then 48 | self.x += self.speed 49 | elseif d == direction.down then 50 | self.y -= self.speed 51 | elseif d == direction.up then 52 | self.y += self.speed 53 | end 54 | end 55 | 56 | function entity:hit(damage) 57 | self.health -= damage 58 | end 59 | 60 | function entity:is_colliding(entity) 61 | return (abs(self.x-entity.x)+ 62 | abs(self.y-entity.y)) <= 8 63 | end 64 | 65 | 66 | 67 | -->8 68 | -- player 69 | 70 | player = {} 71 | player = setmetatable(player, {__index = entity}) 72 | player.__index = player 73 | 74 | function player:init(x, y) 75 | local self = setmetatable(entity:init(x, y, 1), player) 76 | self.health = 100 77 | self.inventory = {} 78 | self.equipment = {} 79 | return self 80 | end 81 | 82 | function player:draw() 83 | entity.draw(self) 84 | self:draw_inventory() 85 | end 86 | 87 | function player:update() 88 | if btn(direction.left) then 89 | self:move(direction.left) 90 | end 91 | if btn(direction.right) then 92 | self:move(direction.right) 93 | end 94 | if btn(direction.down) then 95 | self:move(direction.down) 96 | end 97 | if btn(direction.up) then 98 | self:move(direction.up) 99 | end 100 | end 101 | 102 | function player:add_item(item) 103 | add(self.inventory, item) 104 | end 105 | 106 | function player:equip(item, slot) 107 | self.equipments[slot] = item 108 | end 109 | 110 | function player:draw_inventory() 111 | rect(80, 80, 125, 120, 7) 112 | print("inventory", 84, 84) 113 | for item in all(self.inventory) do 114 | print(item.name, 84, 92) 115 | end 116 | end 117 | 118 | -->8 119 | -- foe 120 | 121 | 122 | foe = {} 123 | foe.__index = foe 124 | setmetatable(foe, {__index = entity}) 125 | 126 | function foe:init(x, y) 127 | local self = setmetatable(entity:init(x, y, 2), foe) 128 | self.atttack = 3 129 | self.health = 10 130 | return self 131 | end 132 | 133 | function foe:attack(target) 134 | if target.health > 0 then 135 | target.hp -= self.attack 136 | end 137 | end 138 | 139 | function foe:update() 140 | entity.update(self) 141 | if self:is_colliding(player) then 142 | self:hit(1) 143 | end 144 | end 145 | -->8 146 | -- item 147 | 148 | equipment_slot = { 149 | head=0, 150 | torso=1, 151 | leg=2, 152 | boots=3, 153 | weapon=4, 154 | } 155 | 156 | item = {} 157 | item.__index = item 158 | 159 | function item:init(name, sprite) 160 | local self = setmetatable({}, item) 161 | self.name = name 162 | self.sprite = sprite or 0 163 | self.x = 30 164 | self.y = 30 165 | return self 166 | end 167 | 168 | function item:draw() 169 | spr(self.sprite, 30, 30) 170 | end 171 | 172 | function item:update() 173 | if self:is_colliding(player) then 174 | world:player_looted_item(self) 175 | end 176 | end 177 | 178 | function item:is_colliding(entity) 179 | return (abs(entity.x-self.x)+ 180 | abs(entity.y-self.y)) <= 8 181 | end 182 | 183 | weapon = {} 184 | weapon = setmetatable(weapon, {__index = item}) 185 | weapon.__index = weapon 186 | 187 | function weapon:init(name, attack) 188 | local self = setmetatable(item:init(name, 0), weapon) 189 | self.attack = attack 190 | self.slot = equipment_slot.weapon 191 | return self 192 | end 193 | 194 | armor= {} 195 | armor = setmetatable(armor, {__index = item}) 196 | armor.__index = armor 197 | 198 | function armor:init(name, defense, slot) 199 | local self = setmetatable(item:init(name, 0), armor) 200 | self.defense = defense 201 | self.slot = slot 202 | return self 203 | end 204 | 205 | 206 | -->8 207 | -- world 208 | 209 | world = {} 210 | world.__index = world 211 | 212 | function world:init() 213 | local self = setmetatable({}, world) 214 | world.items = {} 215 | world.foes = {} 216 | return self 217 | end 218 | 219 | function world:draw() 220 | for item in all(self.items) do 221 | item:draw() 222 | end 223 | 224 | for foe in all(self.foes) do 225 | foe:draw() 226 | end 227 | end 228 | 229 | 230 | function world:update() 231 | for item in all(self.items) do 232 | item:update() 233 | end 234 | 235 | for foe in all(self.foes) do 236 | foe:update() 237 | end 238 | end 239 | 240 | function world:spawn_item(item) 241 | add(self.items, item) 242 | end 243 | 244 | function world:spawn_foe(foe) 245 | add(self.foes, foe) 246 | end 247 | 248 | function world:player_looted_item(item) 249 | player:add_item(item) 250 | del(self.items, item) 251 | end 252 | -->8 253 | -- engine 254 | 255 | state = { 256 | game = 1, 257 | inventory = 2 258 | } 259 | 260 | 261 | function _init() 262 | current_state = state.game 263 | world = world:init() 264 | player = player:init(64, 64) 265 | world:spawn_item(weapon:init("sword", 0)) 266 | world:spawn_foe(foe:init(10, 10)) 267 | end 268 | 269 | function _draw() 270 | cls() 271 | player:draw() 272 | world:draw() 273 | end 274 | 275 | function _update60() 276 | if current_state == state.game then 277 | player:update() 278 | world:update() 279 | end 280 | end 281 | __gfx__ 282 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 283 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 284 | 00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 285 | 00077000000100000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 286 | 00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 287 | 00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 288 | --------------------------------------------------------------------------------