itch.io link:
https://tekkamansoul.itch.io/loto-the-avatar
^
Go here if you want win/linux/osx binaries!
UPDATE 2/14!
It's sort of finished! With music! (Scroll down for dev notes!)
What it is:
A fan's demake of Ultima 1 crossed with Dragon Quest 1. You play as Loto* and your goal is to save the princess and kill the evil wizard Mondain.
INSTRUCTIONS:
Arrows move. You interact/talk/attack by bumping into things.
(O) opens the magic menu where you can cast Hoimi (Heal) and Gira (Firebal).
(X) cancels/closes.
You can only save at Castle British by speaking to Hawkwind.
Your boat may get lost if you die in a dungeon, so be careful!
What you can do:
-Save and load
-Buy a boat and sail
-Use magic
-Reach the max level of 8
-Buy weapons and armor
-Visit the four magic signposts (and get a secret weapon!)
-Delve the four dungeons and kill the four big beasties
-Collect the four magic orbs
-Get the jail key
-Rescue the princess
-Kill the Dragonlord Mondain
..and thats where it stops! Game over, you win.
DISCLAIMER:
This borrows heavily from properties owned by Origin, Enix, EA, and Square-Enix. I made all of the content within the cart but the IPs do not belong to me in any form.
I also would not suggest using this cart as a programming example. I am terrible at coding and this cart is nothing but proof.
glhf
(*not really, you play as their descendant, since that's who you are in DQ1, but eh)
-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-
Development notes!
-There's no actual menu system in the game, but one probably would have saved space. What happens now is draw calls that just plop a rectangle on screen with text and modify key behavior. (Technically this is all a menu/gui system is, but designed properly instead)
-NPCs (and teleport squares) take up a large amount of space, at least in regards to tokens. Taking out one or two is enough for several lines of valuable code, so I had to delete some just to make space for the final bit of code.
-Strangely enough, I never came close to hitting the character limit. I went over compression limit on the cartridge many times, but that was easily fixed by shortening variable names and refactoring. The reason why this is so strange is because the dungeons in the game are stored in strings; 16 total screens, each containing 255 characters (or 4080 chars) that can't be shortened or modified - yet it fits in that 15k cart storage just fine!
-Enemies don't use A* pathfinding, but if they did, it would probably be way more efficient and take less tokens. Right now, they move towards the player one square at a time, and if they're blocked, they might try to move left or right. That's it, and it works fine, but could be better.
-Enemies are actually procedurally generated. Their stats are based on player level and what random monster sprite is picked. They all behave identically, excepting the ones that can pass over water (which was done with a simple sprite flag!)
-Drawing all the 8x8 sprites by hand and manually preening the coastline was totally worth it.
-This doesn't use OOP at all, but for my next Pico-8 RPG I will loo into seeing if it is worth the cost in tokens.
Dude! This game is awesome! I feel like it's one of the best if not THE best developed RPGs on the platform. It feels big, has all the features you would want in a real RPG like equipment, dungeons, townsfolk, and different monsters...4 continents and 8 towns...I wouldn't have expected something like this to be able to fit on the Pico. I've played other RPGs and prototypes on here and they're always lacking in various areas that your game isn't. You did a great job on this.
I mean even to the point of having some enemies able to fly, and some not!
One of the best moments is when I bought the ship and sailed off, and suddenly the world opened up and was 4x bigger than it seemed. Most Pico games would probably stop at the 2 towns and 1 dungeon and call themselves a proof-of-concept.
Your code isn't that bad either, you use some cool tricks like storing dungeons in strings. And overall it's not too hard to read either. I'm really surprised it didn't have to be micro'd to all fit.
I kind of want to make you music for it...nothing that would require a complicated multi-song engine, just something you could play for the whole game. Copy the Dragon Quest 1 castle or town music or something, I dunno. :)
Wow, thanks man, that means a ton.
Go for it! I tried making a Stones remix (the remnants are still in the BGM editor) but it sounded really bad so I muted it out.
If you want to submit music I'll post an update and probably even be inspired to prune down those last hundred tokens to fit the last boss and credits.
Thanks again for the kind words.
It would be really cool to see the game finished.
Would it be ok to do a direct adaptation of a Dragon Quest song, or do you want it to be a remix so it's not "copyright infringing" or whatever?
Also looking at the code I have a couple ideas for optimizations. Now I'm just starting with Pico so I don't know a ton about coding for it, or if these might end up not working quite right, but just throwing them out there:
Do loto.weap and loto.arm have to be _st or "undies" etc.? Those variables could just be the number to add to stats, and you will know that the number stands for "undies" or whatever. So then you could change this:
if(loto.weap==_dg)loto.stren=1+plvl+3 |
to just:
loto.stren=1+plvl+loto.weap |
I suspect you could do another slight reconfiguration so that you could even do
loto.stren=1+plvl+loto.weap+signs[1] |
Where signs[1] is 0 if you haven't read it yet, but 1 once you've read it.
You could then also change how weapons and armor are saved (later using w_int and a_int) and loaded, just store the value stats are increased by directly. Getting rid of all those ifs!
I see potential for massive savings in the scene builder, but it would take a lot of effort too. Looking at blocks like:
elseif i==4 then safe=true mapx=64 mapy=0 maketelep(71,15,0,16,13) maketelep(72,15,0,16,13) makenpc("man",17,69,5,"lord british gives magic\norbs for slaying beasts.",2) makenpc("adventurer",115,65,8,"the legendary beasts\n lurk at bottoms of dungeons.",2) makenpc("man2",17,75,13) makenpc("man3",17,68,13) makenpc("man4",17,67,1) makemerch("weaponsmith",75,12,"buy somethin',\n will ya!",1) makemerch("armorsmith",68,12,"buy somethin',\n will ya!",2) makemerch("innkeep",67,2,"rations? 10 for 5gp,\n or 100 for 50gp!",3) makenpc("british",23,71,1, "go forth and slay an\ngelatinous cube!") makenpc("princess",41,76,1,"you're not supposed to\nbe here") makenpc("hawkwind",11,73,2,"i have saved your game\nand restored you. now go.") makenpc("guard",46,78,4,"the princess is impris-\n oned for her own safety.") |
What if you could store all or most of that in a string, and decompress it out with another function?
Assuming the function wouldn't take up more tokens than those used already.
Could be something where it gets a command from the string, then knows how to interpret the next few pieces of data after that, gets the next command etc.
So just working with 2 statements above as an example:
maketelep(71,15,0,16,13) makenpc("man2",17,75,13) |
You could do something like this:
townstring="10710150000160131man2/017075013......etc.etc." -- leading 0's in the string so that all numbers are consistently 3 digits, you can use strings directly as numbers and leading 0's are discarded |
function decompressstring(townstring) index=1 while(notdoneparsingyet=true) do if sub(townstring,index,1)==1 then -- 1 means maketelep maketelep(sub(townstring,index+1,index+3),sub(townstring,index+4,index+6),sub(townstring,index+7,index+9),sub(townstring,index+10,index+12),sub(townstring,index+13,index+15)) index+=16 elseif sub(townstring,index,1)==2 then -- 2 means makenpc -- code here to extract the npc's name letter by letter, ending when / is encountered, and increment index to the end of the name makenpc(name,sub(townstring,index+1,index+3),sub(townstring,index+4,index+6),sub(townstring,index+7,index+9)) index+=10 |
And so on.
(Alternatively, you could re-code maketelep to accept a constant length string, and it knows how to break it up and doesn't require all those "index+3" token eaters.)
I dunno, that's a lot of work and might not save much, but worth looking into maybe. Again I haven't tested any of it so it's just theoretical to me at this point.
Also see this thread for more discussion on the use of strings as above: https://www.lexaloffle.com/bbs/?tid=28160
Interesting. I know the builder could be optimized quite a bit, that string layout would indeed fit more data, but possibly break over the compression limit. I had to delete all the comments after putting in the dungeon strings, an alternative option there is optimize the dungeon strings from 100000000000000001 to 1W14X1W or somet.
Printing sprites on the map itself then a custom render function would also save those bothersome x and y tokens. Or removing unique names.
I also need to replace the for x in all y do with foreach (x,f), that itself should save enough to finish it.
As for the song have fun with it, do whatever you want :) Not trying to sell this.
Thanks for the detailed help!
Edit: As for weapons that should work. I half added it and didn't care to fix it after adding the catch for weaker weapons in shops but an int is way easier to manage.
Ok, here you go, with music!
At first I had a fancy echo on the town music section, but that was using all 4 channels and it made the sound effects screw up. I settled for changing the instrument during that part instead.
I didn't change anything in your code except adding music(8) during init. Didn't add credit for myself or anything, that's up to you if/where it might fit. I hope you like it!
That sounds awesome. I'll work on finalizing this in the next few days!
Bump, shoehorned in some bugfixes and the final battle. Nothing grand but it fits. Thanks Spooky!
Awesome! I beat the game. Didn't even need the final armor, but got the secret weapon.
I noticed you removed the armor guy from the first castle and the weapon guy from the first town, that's probably a good idea, make the player visit both early on instead of just a one-stop-shop at the castle.
A couple things:
One time, I had all four orbs, saved the game, and closed out, and when I went back I only had the green orb. Level and everything else was saved, and when I revisited the kings I was able to get their orbs again immediately. Something may be wrong with saving orbs. EDIT: Yeah, I just continued again after beating the game and I have the key and just the green orb. I was able to beat the game again with only one orb in my possession because the jail door was open.
Toward the end of the game I was exploring towns looking for the key, and one town actually had monsters spawning in it:
I don't know if this was by design or some sort of accident. They just kept coming as if in a dungeon map.
Hm bizarre! I'll take a look. Hope you enjoyed what's there at least.
Update:
Fixed, they were super easy tweaks. Thanks again !!!!
I just beat this. I really enjoyed it. Probably my favorite PICO-8 game so far.
I did not need the final armor or final sword. I didn't find any secret weapons. I also only ever used the healing spell, as I found the other one less useful.
Great game! Look forward to your next title.
Thanks Bryce!
It is a little easy, it could have used some tweaking for sure. I was afraid of making it too hard. The secret weapon is found at one of the signposts, an NPC has the clue. Gira does your normal attack with 100% accuracy in all 4 directions, so it's really only useful when surrounded.
Thanks for the feedback, glad you liked it!
I liked the difficulty level, especially since scaling monsters means you can't grind to get ahead if that's the experience you want. Really satisfying to finish. :)
[Please log in to post a comment]