Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Okay, I could use some help...

Reply to topic
Author Message
Consolemu
  • Guest
Reply with quote
Okay, I could use some help...
Post Posted: Sun Apr 16, 2000 12:08 am
I'm growing tired of this damn Tetris game. It's not that my codes are wrong but I think my approach is. Here's my method...

1.created a 4x4 array for storing block patterns (pieces that fall)
2.created a 10x20 array for a complete board or map (blank box)
3.in map array (#2), I set up -1's to represent areas that the block cursor(#1) couldn't touch (the sides and the floor or bottom).
4.regular positive 1's represented the pieces that (#1) had set up (or fallen/placed).
5.during the game loop, I would check for input, then react to that input (changing x/y positions, rotation, etc). Before I changed the x/y positions, I would remove the old position from the mapping (#2). Then, after the new coordinates were set, I would merge the piece back into the map. Basically, I constantly merged and unmerged the main cursor (#1) to and from the map.
5.Whenever the player pressed the button for rotation, I would merely rotate the arrangement in the block pattern array(#1) 90 degrees and my game loop would automatically pick up the rotation.

So with all this in it, you could easily rotate and add numerous types of blocks and my engine would try to interpret how the block should react in the map environment.


Major Problems with my approach...
1. During the rotation, the block will tend to jump around inside that 4x4 array. This causes problems when your x coordinate is too far off to the right or too far to the left. The block would wind up getting clipped off. If your block reached the bottom, the coordinate would be right but the pattern shown on the board would be wrong. There would be huge gaps on the map.
2. My colision detection is difficult to check because I can't exactly check every type of pattern in my block pattern array.


With all these problems, the only good thing my game can do is check for lines. What other method should I use to make the programming easier and get the game to work right?

Chris :o)
 
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Post Posted: Sun Apr 16, 2000 2:19 am
I don't particularly see any red flags in the manner you've chosen to implement things. Perhaps you might want to share a speck of source code (either publicly, or just mail it to me) and maybe I can see what's causing the problem.

Some highlights of my approach:

1-I don't rotate the shape manually, rather, I store each rotation as if it were a separate shape. The reason for this is twofold: #1, it saves me from having to write z80 code to rotate the shape -one less headache. The second reason is, in keeping with the classic tetris, not all shapes rotate around a centerpoint.. the stairstep and long bar shapes have only two distinct rotations, and the box doesn't rotate at all. Rather than have to test which shapes use rotations, and how each should be rotated, etc, I just treat each shape definition as an array of four sets of four coordinates, and look up the correct set from the rotation variable.
for instance:
.db 0,-1, 0, 0, 0, 1, -1, 1 ;0
.db -1, 0, 0, 0, 1, 0, -1,-1 ;90
.db 0, 1, 0, 0, 0,-1, 1,-1 ;180
.db 1, 0, 0, 0, -1, 0, 1, 1 ;270
is my definition of the ('backwards' L shape). I just take the rotation number (always 0-3), multiply by 8, and add to the pointer to the above table.

#2-As you can see above, rather than using a 4-by-4 array, I just use four sets of offsets from the 'center' of the piece. It uses 50% fewer bytes and makes my collision detect and puzzle piece plotting routines about twice as fast. Even on the z80, it's barely enough to matter, and on an sort of PC the differences would be neglible. so I guess it's a personal preference.

#3-I don't merge the player controlled shape with the puzzle array until the shape has landed. In the first and second release (the ones without the fancier gfx) I used sprites. In the third and subsequent releases, I've been drawing them right into the tile map, and erasing them the next frame. the puzzle array is used to detect collisions, check if a row is full, and redraw the screen after a row has been removed.

#4-My collision detect routines check each block of the projected puzzle piece against the puzzle array. If any block is filled (something nonzero), or off the left,right, or bottom edge of the puzzle array, it registers as a collision. Since pieces drop in off the top of the screen, blocks which are off the top of the puzzle are not considered collisions. The border around the puzzle (the stoney pieces) are not part of the puzzle array.

#5-The collision detect routine does not do any action of its own, it just returns zero if there's no collision and nonzero (1 or -1, I don't remember) if there is. The collision detector is used by two other parts of the program: When you attempt to move left or right or rotate the piece, the movement routine makes a copy of the current coordinates and rotation values, changes this copy according the the user input, and feeds the copy to the collision detector. If the detector returns nonzero, then the move is rejected, and keeps the previous values. If the detector returns zero, the move is valid and the modified position/rotation replaces the old. When a shape is about to fall one space, we check to see if there would be a collision where the shapewill drop down to. If there isn't, the shape's position is updated. If there is, the updated position is discarded, and the piece is merged into the puzzle array. (scanning, updating, and creating a new shape ensues).

Pardon if this explanation slipped into incomprehensibility, but hopefully it'll give a bit of insight. If you can parse z80 code, you might find it helpful that I'llbe releasing a new version of the tetris source soon.
  View user's profile Send private message Visit poster's website
  • Joined: 12 Jul 1999
  • Posts: 891
Reply with quote
Challenge.....
Post Posted: Sun Apr 16, 2000 4:19 am
Quote
> I don't particularly see any red flags in the manner you've chosen to implement things. Perhaps you might want to share a speck of source code (either publicly, or just mail it to me) and maybe I can see what's causing the problem.

> Some highlights of my approach:

> 1-I don't rotate the shape manually, rather, I store each rotation as if it were a separate shape. The reason for this is twofold: #1, it saves me from having to write z80 code to rotate the shape -one less headache. The second reason is, in keeping with the classic tetris, not all shapes rotate around a centerpoint.. the stairstep and long bar shapes have only two distinct rotations, and the box doesn't rotate at all. Rather than have to test which shapes use rotations, and how each should be rotated, etc, I just treat each shape definition as an array of four sets of four coordinates, and look up the correct set from the rotation variable.
> for instance:
> .db 0,-1, 0, 0, 0, 1, -1, 1 ;0
> .db -1, 0, 0, 0, 1, 0, -1,-1 ;90
> .db 0, 1, 0, 0, 0,-1, 1,-1 ;180
> .db 1, 0, 0, 0, -1, 0, 1, 1 ;270
> is my definition of the ('backwards' L shape). I just take the rotation number (always 0-3), multiply by 8, and add to the pointer to the above table.

> #2-As you can see above, rather than using a 4-by-4 array, I just use four sets of offsets from the 'center' of the piece. It uses 50% fewer bytes and makes my collision detect and puzzle piece plotting routines about twice as fast. Even on the z80, it's barely enough to matter, and on an sort of PC the differences would be neglible. so I guess it's a personal preference.

> #3-I don't merge the player controlled shape with the puzzle array until the shape has landed. In the first and second release (the ones without the fancier gfx) I used sprites. In the third and subsequent releases, I've been drawing them right into the tile map, and erasing them the next frame. the puzzle array is used to detect collisions, check if a row is full, and redraw the screen after a row has been removed.

> #4-My collision detect routines check each block of the projected puzzle piece against the puzzle array. If any block is filled (something nonzero), or off the left,right, or bottom edge of the puzzle array, it registers as a collision. Since pieces drop in off the top of the screen, blocks which are off the top of the puzzle are not considered collisions. The border around the puzzle (the stoney pieces) are not part of the puzzle array.

> #5-The collision detect routine does not do any action of its own, it just returns zero if there's no collision and nonzero (1 or -1, I don't remember) if there is. The collision detector is used by two other parts of the program: When you attempt to move left or right or rotate the piece, the movement routine makes a copy of the current coordinates and rotation values, changes this copy according the the user input, and feeds the copy to the collision detector. If the detector returns nonzero, then the move is rejected, and keeps the previous values. If the detector returns zero, the move is valid and the modified position/rotation replaces the old. When a shape is about to fall one space, we check to see if there would be a collision where the shapewill drop down to. If there isn't, the shape's position is updated. If there is, the updated position is discarded, and the piece is merged into the puzzle array. (scanning, updating, and creating a new shape ensues).

> Pardon if this explanation slipped into incomprehensibility, but hopefully it'll give a bit of insight. If you can parse z80 code, you might find it helpful that I'llbe releasing a new version of the tetris source soon.

OK, so I didn't understand that (duh!)..... but I take it that you're not going to have lovely little animations for the rotation of the blocks?

Ah well.......

~unfnknblvbl
  View user's profile Send private message
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Re: Challenge.....
Post Posted: Sun Apr 16, 2000 4:28 am
Quote
> OK, so I didn't understand that (duh!)..... but I take it that you're not going to have lovely little animations for the rotation of the blocks?

> Ah well.......

Er, why do you bring it up? What sort of animations do you have in mind?

I'm thinking of adding animation elsewhere, but keeping the block rotation fairly simple.
  View user's profile Send private message Visit poster's website
Consolemu
  • Guest
Reply with quote
Hum...
Post Posted: Sun Apr 16, 2000 5:10 am
Quote
> 1-I don't rotate the shape manually, rather, I store each rotation as if it were a separate shape. The reason for this is twofold: #1, it saves me from having to write z80 code to rotate the shape -one less headache. The second reason is, in keeping with the classic tetris, not all shapes rotate around a centerpoint.. the stairstep and long bar shapes have only two distinct rotations, and the box doesn't rotate at all. Rather than have to test which shapes use rotations, and how each should be rotated, etc, I just treat each shape definition as an array of four sets of four coordinates, and look up the correct set from the rotation variable.
> for instance:
> .db 0,-1, 0, 0, 0, 1, -1, 1 ;0
> .db -1, 0, 0, 0, 1, 0, -1,-1 ;90
> .db 0, 1, 0, 0, 0,-1, 1,-1 ;180
> .db 1, 0, 0, 0, -1, 0, 1, 1 ;270
> is my definition of the ('backwards' L shape). I just take the rotation number (always 0-3), multiply by 8, and add to the pointer to the above table.

The main problem was the fact that I was trying to convert coordinates and bitmaps and that confused my program (as well as the user). My bitmapped arrays were kinda like this...


bitmap(0) = 0110
bitmap(1) = 0010
bitmap(3) = 0010
bitmap(4) = 0000


My code was exactly like this...

pattern(0,0) = 0
pattern(1,0) = 1
pattern(2,0) = 1
pattern(3,0) = 0

...
*And so on*

But I'm too lazy to type that. This is what my rotation code is exactly like...

Dim temppattern(4, 4) As Integer

temppattern(0, 0) = pattern(0, 3)
temppattern(1, 0) = pattern(0, 2)
temppattern(2, 0) = pattern(0, 1)
temppattern(3, 0) = pattern(0, 0)

temppattern(0, 1) = pattern(1, 3)
temppattern(1, 1) = pattern(1, 2)
temppattern(2, 1) = pattern(1, 1)
temppattern(3, 1) = pattern(1, 0)

temppattern(0, 2) = pattern(2, 3)
temppattern(1, 2) = pattern(2, 2)
temppattern(2, 2) = pattern(2, 1)
temppattern(3, 2) = pattern(2, 0)

temppattern(0, 3) = pattern(3, 3)
temppattern(1, 3) = pattern(3, 2)
temppattern(2, 3) = pattern(3, 1)
temppattern(3, 3) = pattern(3, 0)


pattern(0, 0) = temppattern(0, 0)
pattern(1, 0) = temppattern(1, 0)
pattern(2, 0) = temppattern(2, 0)
pattern(3, 0) = temppattern(3, 0)

pattern(0, 1) = temppattern(0, 1)
pattern(1, 1) = temppattern(1, 1)
pattern(2, 1) = temppattern(2, 1)
pattern(3, 1) = temppattern(3, 1)

pattern(0, 2) = temppattern(0, 2)
pattern(1, 2) = temppattern(1, 2)
pattern(2, 2) = temppattern(2, 2)
pattern(3, 2) = temppattern(3, 2)

pattern(0, 3) = temppattern(0, 3)
pattern(1, 3) = temppattern(1, 3)
pattern(2, 3) = temppattern(2, 3)
pattern(3, 3) = temppattern(3, 3)

If pattern(3, 0) = 1 Or pattern(3, 1) = 1 Or pattern(3, 2) = 1 Or pattern(3, 2) = 1 Then
X = X - 1
End If
If pattern(0, 0) = 1 Or pattern(0, 1) = 1 Or pattern(0, 2) = 1 Or pattern(0, 3) = 1 Then
X = X + 1
End If

If pattern(0, 0) = 1 Or pattern(1, 0) = 1 Or pattern(2, 0) = 1 Or pattern(3, 0) = 1 Then
Y = Y + 1
End If

If pattern(0, 3) = 1 Or pattern(1, 3) = 1 Or pattern(2, 3) = 1 Or pattern(3, 3) = 1 Then
Y = Y - 1
End If
End Sub


I copy and pasted that one. As you can see I tried to fix my problem by adjusting the coordinates at the last minute and it worked for some blocks but not all. It actually broke some blocks like the stair and the box (yes the box jerked because of that code).

Anyway, my brain is beginning to brainstorm but some of what you said I don't understand. You're keeping a pattern of the block in 4 arrays for 4 directions? Gotta remember that I'm new to this.

Chris :o)
 
Consolemu
  • Guest
Reply with quote
Something kinda funny...
Post Posted: Sun Apr 16, 2000 5:22 am
It seems like every kind of game I try to jump to, I run into some brain scratching problems. Tetris...

Pros: Easy to detect lines. Easy to update.
Cons: Rotation of Blocks. Keeping pieces in boundary.

Columns...

Pros: Easy to update. No rotation of blocks.
Cons: Difficult line detection.

Klax...
Pros: No rotation of pieces.
Cons: Keeping hand inline with falling pieces. Difficult line detection. Animating pieces that roll down convayer belt.

Nibbles (Worms)
Pros: Easy colision detection. No rotation. Easy to update.
Cons: Getting the body of the worm to stay in direction of the head. Making the worm larger or smaller.

Checkers...
Pros: Easy colision detection. no rotation. Easy path movement.
Cons: Getting queens to stay in bounds. Double jumping.

Dig Dug...
Pros: No rotation. Easy to update.
Cons: Colision detection. Moving through the dirt (digging). Making the enemies float through the dirt.

Pac Man...
Pros: Easy colision detection.
Cons: AI for the ghosts.

Or mabye I just figured out that every video game that seems easy to code has it's difficult pitfalls.

Chris :o)
 
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Re: Hum...
Post Posted: Sun Apr 16, 2000 7:43 am
Quote
> The main problem was the fact that I was trying to convert coordinates and bitmaps and that confused my program (as well as the user). My bitmapped arrays were kinda like this...

>
> bitmap(0) = 0110
> bitmap(1) = 0010
> bitmap(3) = 0010
> bitmap(4) = 0000
>


hell, just use arrays. Even the sms doesn't hurt for memory so bad that you need to use bitmaps.

Quote
>
> Dim temppattern(4, 4) As Integer

> temppattern(0, 0) = pattern(0, 3)
> temppattern(1, 0) = pattern(0, 2)
> temppattern(2, 0) = pattern(0, 1)
> temppattern(3, 0) = pattern(0, 0)

> temppattern(0, 1) = pattern(1, 3)
> temppattern(1, 1) = pattern(1, 2)
> temppattern(2, 1) = pattern(1, 1)
> temppattern(3, 1) = pattern(1, 0)

> temppattern(0, 2) = pattern(2, 3)
> temppattern(1, 2) = pattern(2, 2)
> temppattern(2, 2) = pattern(2, 1)
> temppattern(3, 2) = pattern(2, 0)

> temppattern(0, 3) = pattern(3, 3)
> temppattern(1, 3) = pattern(3, 2)
> temppattern(2, 3) = pattern(3, 1)
> temppattern(3, 3) = pattern(3, 0)

>
> pattern(0, 0) = temppattern(0, 0)
> pattern(1, 0) = temppattern(1, 0)
> pattern(2, 0) = temppattern(2, 0)
> pattern(3, 0) = temppattern(3, 0)

> pattern(0, 1) = temppattern(0, 1)
> pattern(1, 1) = temppattern(1, 1)
> pattern(2, 1) = temppattern(2, 1)
> pattern(3, 1) = temppattern(3, 1)

> pattern(0, 2) = temppattern(0, 2)
> pattern(1, 2) = temppattern(1, 2)
> pattern(2, 2) = temppattern(2, 2)
> pattern(3, 2) = temppattern(3, 2)

> pattern(0, 3) = temppattern(0, 3)
> pattern(1, 3) = temppattern(1, 3)
> pattern(2, 3) = temppattern(2, 3)
> pattern(3, 3) = temppattern(3, 3)

Blarf. Why not use loops? I'm not familiar with how visual basic implements for loops, but in C it'd be esy enough with a loop nested in a loop.


for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
temppattern[i][j] = pattern[j][3 - i]
}
}
memcpy(pattern, temppattern, sizeof(pattern));

something like that. I'm sure I left a bug in there somewhere.



Quote
> If pattern(3, 0) = 1 Or pattern(3, 1) = 1 Or pattern(3, 2) = 1 Or pattern(3, 2) = 1 Then
> X = X - 1
> End If
> If pattern(0, 0) = 1 Or pattern(0, 1) = 1 Or pattern(0, 2) = 1 Or pattern(0, 3) = 1 Then
> X = X + 1
> End If

> If pattern(0, 0) = 1 Or pattern(1, 0) = 1 Or pattern(2, 0) = 1 Or pattern(3, 0) = 1 Then
> Y = Y + 1
> End If

> If pattern(0, 3) = 1 Or pattern(1, 3) = 1 Or pattern(2, 3) = 1 Or pattern(3, 3) = 1 Then
> Y = Y - 1
> End If
> End Sub
>


> I copy and pasted that one. As you can see I tried to fix my problem by adjusting the coordinates at the last minute and it worked for some blocks but not all. It actually broke some blocks like the stair and the box (yes the box jerked because of that code).

Best to let your collision detection system ensure that the piece is in a valid location.


Quote
> Anyway, my brain is beginning to brainstorm but some of what you said I don't understand. You're keeping a pattern of the block in 4 arrays for 4 directions? Gotta remember that I'm new to this.

I define each shape definition as an array of four 'shapes', each 'shape' being an array of four 'coordinates', each coordinate consisting of two bytes.


Each coordinate is an x/y offset pair from the center of the piece (0,0), and defines 1 block of the shape.
Each 'shape' (my terminology gets confusing, so bear with me) consists of four coordinates. The four coordinates define the four blocks that make up the shape. For instance, the following set: { {0,-1}, {0,0}, {0,1}, {1,1} } defines an 'L' shape (do you see how?)). We might stop there if we were planning to rotate the shape manually each time, however, we're going to store all four rotations of the shape, so we have:
A shape definition, which consists of 4 'shapes'. Each shape is identical to the other shapes, except that it has been rotated at 90 degree intervals. For instance, the full definition of the L shape is:


{
{ {0,-1}, {0,0}, {0,1}, {1,1} }, //A standing 'L', at 0 degrees
{ {-1,0}, {0,0}, {1,0}, {1,-1}}, //at 90 degrees (from original)
{ {0,1}, {0,0}, (0,-1}, {-1,-1}, //at 180 degrees (upside down and backwards.)
{ {1,0}, {0,0}, {-1,0}. {-1, 1} //and at 270 degrees
}


So, let's see what the datatypes for that would look like in C:


typedef struct COORDINATE
{
char x;
char y;
};

typedef struct SHAPE
{
COORDINATE offsets[4];
};

typedef struct SHAPEDEF
{
SHAPE rotations[4];
}


Now, let's say we want to plot the L shape rotated 180 degrees (rotation '2') in the middle of the puzzle array. We might have the following function:


void DrawShape(SHAPEDEF *shapedef, int rot, int x, int y)
{
int i;
int tx,ty;
for(i = 0; i < 4; i++)
{
tx = shapedef->rotations[rot].offsets[i].x + x;
ty = shapedef->rotations[rot].offsets[i].y + y;
if( tx >= 0 && tx <=9 && ty >=0 && ty <= 19)
{
FillInBox(tx, ty);
}
}
return;
}


Assuming a FillInBox function which fills in a given box on the puzzle display. (you might have aversion that fills in a value on the interal puzzle array only, and one that fills it in on the screen only, and use the right tool for the job)

Just call DrawShape(&lshapedef, 2, 5, 10); and the routine will use the third set of offset pairs to draw the upsidedown and backwards L shape in the middle of the screen (or stamps it into the puzzle array, depending on what FillInBox() does).

In z80, this would take a lot more code. a LOT. but the concept is very much the same.

Get the basic concept now?
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Re: Something kinda funny...
Post Posted: Sun Apr 16, 2000 7:49 am

Quote
> Or mabye I just figured out that every video game that seems easy to code has it's difficult pitfalls.

That's true...
Tetris was a good starting game for you: it's a very simple game, probably about the simplest puzzle game (I'd say the simplest action game is probably the snake game (aka 'nibbler')).
Yes, it seems difficult now, and I call it easy. But the thing is, you're relatively new to the logical processes behind creating games and solving more complicated programming tasks.
The good news is: you get better. With practice.
  View user's profile Send private message Visit poster's website
  • Joined: 12 Jul 1999
  • Posts: 891
Reply with quote
Re: Challenge.....
Post Posted: Sun Apr 16, 2000 8:31 am
Quote
> > OK, so I didn't understand that (duh!)..... but I take it that you're not going to have lovely little animations for the rotation of the blocks?

> > Ah well.......

> Er, why do you bring it up? What sort of animations do you have in mind?

> I'm thinking of adding animation elsewhere, but keeping the block rotation fairly simple.


I was just thinking of a quick 2,3 or 4 frame animation from one rotation to another.....

Pretty cool game though.... keep up the good work!

~unfnknblvbl
  View user's profile Send private message
vecna
  • Guest
Reply with quote
Columns
Post Posted: Sun Apr 16, 2000 7:03 pm
Quote
> Columns...

> Pros: Easy to update. No rotation of blocks.
> Cons: Difficult line detection.

Columns really isn't so bad. I don't know if this'll help you any, or if you're interested, but I did a goofy project a couple months ago for a friend of mine's art project called Sully Columns (it's based on the original VERGE pack-in game, Sully Chronicles). The source code is available, if you wanna check it out. The source isn't immaculate since it was a 2 day project, but you can check out the line detection code or whatever. Hint: Just have one loop that scans for horizontal lines, a second loop that scans for vertical lines, and 3rd and 4th loops that do + and - diagonal scans.

You can get it here.

- vecna
 
Chris
  • Guest
Reply with quote
Ha ha!
Post Posted: Sun Apr 16, 2000 7:22 pm
Man, that thing is great! I like the little in-game dialog between the devil and the hero guys. I got a triple and the devil said, "Bah! Your mother eats paint chips!" and the hero said, "Oh, you mean wall candy?". I dunno if you knew or not but there was a major bug in it. When I got to the top and I had 3 purple gems, the game got locked on that one piece and my score really racked up bigtime!

Chris :o)
 
Reply to topic



Back to the top of this page

Back to SMS Power!