[Game]Pokittobloids

Hi guys.

Took me about two weeks (but I’ve been super motivated!) to put this game together.

I love this game on the C64 and decided it would make a great concept for my first game on the Pokitto to learn micro python and the like.

Instructions:
A: start game. Hold B to view instructions. Left: Music on, Right: Music off.

In-game, D-pad: move face pieces in the middle to top, right, bottom or left boxes. Button B uses a coin to buy a new center piece if the existing one doesn’t fit anywhere. However, as a penalty, a random box will get cleared.

For Windows:

  1. Download the pokittobloidsWindows.zip file.
  2. Extract it to your desktop or wherever you want,
  3. Double click the PokittoEmu.exe to start the game.

PLEASE NOTE: There is no audio in the Windows emulator.
Enjoy!

Tools I used:
Aseprite (graphics)
Bfxr (sfx)
Audacity
Deflemask (music)
Online Micropython IDE (code)

Let me know what you think and please don’t be too brutal :smile:

bloids

11

2

3

Release:

Here’s the zip file with everything in it, including the bin, readme and wav files for the music:
pokittobloids.zip (1.0 MB)

Windows:
pokittobloidsWindows.zip (1.6 MB)

Am I allowed to put my game onto my own website for download too?

Best,
Jaco

10 Likes

Of course!

Change the title from [Game] Pokittoloids to [Game]Pokittobloids (no space)

Then select tags “game” “release” and one of the available game types, for example “action” or “puzzle” (not both)

A gif in the size 440 x 352 needs to be the first image if you want it to be same formatting as other games.

I use the PokittoEmu to record a gameplay gif, then I use (if needed) ezgif.com to resize or speed up the gif

Looks very nice!

Please, add a “micropython” tag also.

2 Likes

@jvdw007

Hi Jaco! Nice game! I was testing it, so I while I was at it I made the gif and made this downloadable.

1 Like

Thanks guys for the feedback and also the help with the gif animation etc.
I’ve made some changes to the game which makes it even more fun and challenging.
Just need to implement some more graphics and code now, then I’ll upload the latest version (more complete) here to replace the one in my first post.

3 Likes

Ok guys,

I’ve uploaded a new version of the game with instructions and the ability to clear a random block of faces using B button that uses coins.

Known issues:
Random generation isn’t that good, so you often get a piece that you can’t place. Sometimes it’s just dumb luck. I’ll need to look into maybe changing the code to compare the current and previous random pieces and if they’re in the same spot, to change it… (Good idea I think)
You should get a bonus coin for every 1000 points. However you only get that once now when hitting 1000 or more. I need to figure out how to implement it for every 1000, because the score can be 1000, or 1010, or 1200 from the previous 900 or 990 etc etc… This is gonna take some thought., unless someone knows how to do something like that?

Anyway, thanks and enjoy!

3 Likes

I could have a look, but it would be a lot easier to do so if the code were available e.g. on GitHub (and preferably if it were open source).


We should really make some kind of “how to publish a game” tutorial specifying all these things.

1 Like

My code is terrible and I daren’t place it on github. Maybe once I do better Python coding I’ll revisit that option.

I’ve uploaded a new version of the game, where you now get granted a coin each time you complete a face, and 2 coins if you complete a face of same type. Makes the game a LOT easier… Maybe too easy?

That’s not a reason, that’s an excuse. :P

Seriously though, I guarantee most of us have seen and even written worse code.

If you’re really that worried then you could PM it to me and I could have a quick look.
I’ll try to solve your problems without the code anyway…


Having actually had a chance to play the game and understand the rules I think I know how you could solve this.
(You might want to add a screenshot of the rules screen to the main post by the way.)

Each head has 4 parts: top left, top right, bottom left and bottom right.
If you count the number of each part placed then you know how many of each type you can still generate.
For example if partsPlacedTopLeft were 3 then you know you can generate 1 more top left pice,
but if it were 4 then you know you’re not allowed to generate a new one because the player can’t place it.

You could also do this the other way around, have partsFreeTopLeft start at 4 and then decrease it every time a part is placed.

Anyway, when you come to generate a part, what you can do is look at the part counters for each face part type, determine if you’re allowed to generate a part of that type and if you are you add that part type to a list.
When you’ve done that for each part you randomly select a part type from that list, which will mean you end up only selecting part types that you’re allowed to generate.

It might actually be cheaper to modify that list at the same time you modify the part counter, but I’m not completely sure.

Edit
An example of what the code might look like using the ‘decrement’ approach:

def generate_piece():
  piece_shapes = []
 
  if (available_top_left_pieces > 0):
    piece_shapes.append(PieceShapes.top_left)

  if (available_top_right_pieces > 0):
    piece_shapes.append(PieceShapes.top_right)

  if (available_bottom_left_pieces > 0):
    piece_shapes.append(PieceShapes.bottom_left)

  if (available_bottom_right_pieces > 0):
    piece_shapes.append(PieceShapes.bottom_right)

  # The same 'select_random' I demonstrated in the other thread:
  # https://talk.pokitto.com/t/file-name-based-on-random-numbers/1898/8
  piece_shape = select_random(piece_shapes)

  # However you're doing that
  piece_type = generate_piece_type()
  
  return Piece(piece_shape, piece_type)

There might be arguably more ‘pythonic’ ways to do this, but this is the second cheapest and perhaps the simplest way I can think of doing this.

I’ll try to guess this one without seeing your code…

I’m guessing right now you’re using a boolean to decide if the bonus coin has been awarded?
Either that or you’re using a counter of some kind and your logic test is only firing for the first increase.

Either way there’s an easy solution. At the point at which you add to the player’s score (which hopefully is a function called add_points or add_score or something like that), you:

  • Store a copy of the old score
  • Add to the score
  • Compare the old score divided by 1000 to the new score divided by 1000
    • If the new score divided by 1000 is larger than the old score divided by 1000 then you add a coin
    • Otherwise, do nothing

Or, something more Pythony:

def add_score(amount):
  old_score = player_score
  player_score += amount
  if ((old_score / 1000) < (player_score / 1000)):
    player_coins += 1

Hey Jaco! That’s a line that almost everyone here has used, including me.

So don’t worry. Everybody understands what it is to get started, but if your code is visible we can satisfy our urge to help - which is part of the fun of being here.

5 Likes

@Pharap

Thanks for the code ideas. The score / 1000 idea was very elegant, but doesn’t work as only INTs are supported and not Floats, so what I did was this:

if ((score > 1000 and oldScore == 0) or (score > 2000 and oldScore == 1000) or (score > 3000 and oldScore == 2000) or (score > 4000 and oldScore == 3000) or (score > 5000)):
                coins += 3
                oldScore += 1000

So my idea behind this is you get awarded coins up to a point. If you can reach 5000 points, you’re doing well enough to not need more :slight_smile:

In any case, I like the twist my version of this game provides. The challenge of putting face pieces on the boards, but also making an extra challenge when you’re hit with a piece you can’t place, then having to pay for a new piece with a coin. You get award coins for completing faces anyway, so I think the system works well.

@jonne

I will put the code onto Github when I get a chance. As luck would have it, I’m starting a new job tomorrow, so that’s taking higher priority at this point in time.

Will update this thread when I’ve put the code up.

Thanks!

It shouldn’t need floats, it actually depends on integer logic.
If the division resulted in floating points then it actually wouldn’t work.

Here’s a worked example:

  • player_score is 980, amount is 50
  • old_score is set to 980
  • amount is added to player_score, player_score becomes 1030
  • old_score / 1000 is 0, player_score / 1000 is 1, thus ((old_score / 1000) < (player_score / 1000)) so player_coins += 1

Similarly:

  • player_score is 1000, amount is 50
  • old_score is set to 1000
  • amount is added to player_score, player_score becomes 1050
  • old_score / 1000 is 1, player_score / 1000 is 1, thus ((old_score / 1000) < (player_score / 1000)) isn’t true, so player_coins += 1 doesn’t happen

This should work for any multiple of 1000.

If it’s not working then there must be something else causing problems.

Perhaps the numbers are floating points?
If so using (int(old_score / 1000) < int(player_score / 1000)) or (floor(old_score / 1000) < floor(player_score / 1000)) should work.


At any rate, you could simplify your new code’s logic to:

if ((score < 5000) and ((score / 1000) > (oldScore * 1000))):
   coins += 3
   oldScore += 1

Using your code

if ((score < 5000) and ((score / 1000) > (oldScore * 1000))):

…this is what I got (I keep getting this with divisions):

File "main.py", line 1569, in updateFaces
TypeError: unsupported types for : 'int', 'int'

In any case, my solution works and I’m happy enough with it. I’ve set up a Github account and committed the source to it. You can find it here:

https://github.com/jvdw008/pokittobloids/tree/version13

After laughing at my code, please be aware that I haven’t gotten around to improving the way the sound works. I had to have the sound data in the main file for it to work. (Can’t remember why now).

There also seems to be some repetitive code, but I’ll aim to improve it when I have time.

I like the game as it now works, so I’m hapy enough with it game-wise. Just need to improve the code :slight_smile:

You need to use // instead of / I think to get integer division

3 Likes

Thanks @sbmrgd

I’ll look into it when I get some time.

In the meantime, some features I plan to add:

  1. Some more sounds to distinguish between certain events.
  2. When it’s game over, the game will add up your left over coins to your score.
  3. Music.
  4. Extra bonus when you clear all faces on the screen.
  5. A different sound for when using a coin (at the moment all button presses use the same sound)

Gah, you’re right.

Dagnabbit Python, that’s a weird design decision.
I haven’t seen a separate integer division operator since Visual Basic.

It looks mostly fine overall.
You’re using classes at least, which is a big bonus.

I can see a handful of possible improvements,
but it’s been a long day, so I’ll wait till tomorrow before making any suggestions.
Though I will say: think for loops.

2 Likes

It is, and the language founder agrees.

2 Likes

I’ve started slowly replacing repetitive code with for loops and making other general improvements. Should hopefully be done in a week or less.

3 Likes

I thought it was a bad coder joke but it’s actually true

1 Like

I’m glad he recognises the flaw.

Many people praise Python for various reasons, but much like C++ it’s a language old enough to suffer from the occaisional misjudged historical decision.

Unrelated: the article says “an ado about nothing”, but the word ‘ado’ is uncountable, so the ‘an’ is ungrammatical.

Sadly yes.

Visual Basic is another language that has an integer division operator (\).
Interestingly they’re both from the early 90s.
However the ‘ABC’ language mentioned in that article which apparently has an integer division operation is from the 80s,
so I’m guessing that probably influenced VB as well as Python.

At any rate, I think most people have learnt their lesson about having a separate ‘integer division’ operator by now.
Operator overloading (and arguably basic type theory) renders it obsolete.


If you want any suggestions don’t be afraid to ask.