Showing posts with label games. Show all posts
Showing posts with label games. Show all posts

6.28.2010

New Android game, Scribe: Coming soon!

Remember how I said I would update this blog, like, all the time? Me neither. Anyway, I'm working on a game for Android called Scribe (pdf):
Scribe is a pen and paper game for two players. Nine mini grids together form one super grid. The 19 glyphs of Scribe are listed in the left margin. Draws cannot occur in Scribe. Mark Steere invented Scribe on October 1, 2006.
I've played a sort of "play by email" version of it at superdupergames and I always thought it would be more fun in real time, so I decided to make it my first Android development project. I've already cranked out all the data structures and tricky logic (specifically, the difficult task of figuring out who won a particular mini-grid), so all that's left is the UI. As it's my first Android project, I don't know how long it will take, but my (admittedly rather arbitrary) goal is to have a beta version ready for download by the beginning of August.

If you want to follow along with the development, keep an eye on my github account. (The Scribe project that's up there now is a desktop version, hastily thrown together in Swing, but I couldn't get the github "downloads" feature to work, so you'll have to build it from source, or wait a little while.)

In the meantime, can you prove Mark Steere's claim that ties are impossible?

1.29.2010

Old games with a twist

I love casual games. I don't know if there's a strict definition for a "casual game" but I would say it's a small, simple game that you can learn very quickly. The kind of free flash games you find at places like Kongregate or Armor Games or Jay is Games. Lately I've seen a few fun games that are all twists on very familiar games, or combinations of them.

  • In Tuper Tario Tros, you're playing Mario and Tetris at the same time, in the same place. The tetris blocks that fall become the terrain that Mario is running and jumping on. If Mario can't make it across a gap, switch to Tetris mode and build him a bridge out of tetrominoes. If you can't find anywhere to put your current block, switch back to Mario mode and move through the landscape until you find a more favorable area.
  • First-Person Tetris is more or less what it sounds like. It's tetris but you are the tetris block! Warning: This game will make you dizzy and perhaps naseous if you play it enough.
  • gnop (yes, that's "pong" backwards) is a clone of Pong, except that you are the ball. Perhaps it was inspired by First-Person Tetris. While playing this one, I imagine that some kid in the 80s with a bad haircut is playing pong, and is wondering why the ball refuses to follow the laws of physics.
  • Lastly, I just discovered TetriSnake which is of course a tetris game where instead of blocks, you have little snakes. Which is cool because they can be any shape you want if you can succesfully maneuver them into that shape.
  • UPDATE: Found another one: Anti-Pacman, where you control the four ghosts. In fact, this is part of an Anti-Games series, but of all the ones listed, Anti-Pacman sounds like the coolest.
Do you know of any other casual games in this "classic(s) with a twist" category? What two games should be mashed up next?

8.09.2009

TDD with Infinitest

As I posted last time, I'm writing a game in Java called Flood It, copied from inspired by the game of the same name by Lab Pixies. I encourage you to play it and if you find any bugs, or would like to request enhancements, add an issue in the issue tracker. In fact, if you do play it, you'll probably understand this post better.
One of the most important classes in the game is called Grid: It represents the big grid of squares and also keeps track of which ones are in the upper-left group. Because it's so important, I decided to write some unit tests for it, because that's supposed to be the best way to write great code and all that. I'm also using a great little tool called Infinitest which continuously runs your tests for you in the background, all the time. What happened just now is, I think, a great example of why everyone says unit testing is so important.

The constructor for Grid takes a width, a height, and a number of colors. It picks some colors and then populates the grid with a random assortment of squares. So far, so good. But I'm trying to implement an undo/redo feature so I think I'm probably going to need to override clone(). In this case, the constructor will fill the grid with a bunch of incorrect squares, only to have the clone() method overwrite all that data. I decided not to worry about it. Here was my original clone() method:

protected Grid clone() {
Grid clone = new Grid(this.getWidth(), this.getHeight(), this.colors.size());
clone.colors = this.colors;
for (int x=0; x<getWidth(); x++) {
for (int y=0; y<getHeight(); y++) {
clone.data[x][y] = this.data[x][y].clone();
}
}
clone.update();
return clone;
}
The update() method just checks for any squares that may have suddenly become part of the upper left group because the player changed the color of the group, and adds them to the set. Can you see the bug yet? There are actually two bugs, very closely related. I might have caught both of them eventually by playing the game itself, but this method isn't called anywhere in the actual game yet so that might not be until a few days from now. Luckily, I thought to write a unit test:


private void testClone(Grid orig) {
Grid clone = orig.clone();

System.out.println("Original:");
System.out.println(orig);
System.out.println("Clone:");
System.out.println(clone);

assertEquals(orig.getWidth(), clone.getWidth());
assertEquals(orig.getHeight(), clone.getHeight());
assertEquals(orig.getColors().size(), clone.getColors().size());
assertEquals(orig.getNumInUpperLeftGroup(), clone.getNumInUpperLeftGroup());

for (Color color : orig.getColors()) {
assertTrue(clone.getColors().contains(color));
}

for (int x=0; x<orig.getWidth(); x++) {
for (int y=0; y<orig.getHeight(); y++) {
Square origSquare = orig.get(x,y);
Square cloneSquare = clone.get(x,y);
assertNotSame(origSquare, cloneSquare);
assertTrue(origSquare.sameColor(cloneSquare));
}
}
}

Actually, it was the comparison of the toString() outputs that led me to the first bug. Then I decided to add the getNumInUpperLeftGroup() method and use it in the unit test, which led me to the second bug. Which is why you shouldn't put information in toString() that's not accessible somewhere else. But anyway. The first bug was that clone.update() was not adding anything to the upper left group. I knew this because the toString() showed squares in the upper left group as capital letters and others in lowercase. In the clone, it was all lowercase. What was wrong with the clone's update() method? Nothing, actually. For a Grid constructed normally, the last thing in the constructor is upperLeftGroup.add(get(0, 0)); and then update(); My new grid needed that first square to "seed" the update method. So I added clone.upperLeftGroup.add(clone.get(0,0)); to the bottom of the clone() method, before the update, and ran the test again. This time the toString() outputs matched perfectly, but the test still failed.

I leave it as an exercise to the reader to find the second bug. And by that I mean I'm tired of typing so I'll post it later. But suffice it to say that without this unit test having caught the second bug, I might have had some very strange behavior that only showed up in a very particular case. It might have gone uncaught for weeks and when I did find it, it would have driven me crazy and taken me quite a long time to figure out.

This is why everyone says unit testing is so important. I think I get it now.

8.06.2009

New project: Flood It

Through a stroke of luck, I managed to gain possession of an iPhone for a few days, and I downloaded a game I really liked called Flood It. Knowing I'd only have the iPhone for a few days, and not knowing whether any implementations of the game existed online anywhere, I decided to try and make my own, and try to learn a little about Swing and GUI programming as I go.

If you have Java, download it and play it and let me know what you think. Hopefully I will continue working on it at least a little every day so try it out and if you have any suggestions or bug reports, put them in the issue tracker (I don't know if you need a Google account or what).

Enjoy!

1.05.2008

Portal Physics

I really want to post with some consistency, even if I'm just rambling. So tonight, I will be rambling about the physics of the popular video game Portal. In case you're unfamiliar, you can read about it online, but basically, you're in an enclosed room, armed with nothing but a special portal gun. Shoot it at a wall to create a bluish portal, and at another wall to create an orangish portal. As if by magic, the two portals will be connected, so that you can send any object, including light, or yourself, through one portal, and it will come out the other. You use this to transport yourself or other objects to places that would otherwise be unreachable. It looks kind of like an FPS, but it's actually more of a puzzle game, which is why I like it. Of course, teleportation in video games isn't new, but what's unique about Portal is that the momentum of objects is also transferred through the portal, which leads to some very interesting solving techniques. For example, if you're on a high "cliff" next to a wide, deep chasm, and you need to get across the chasm, but can't create a portal on the other side (some walls resist the portal gun), you can shoot one portal in the wall next to you, so that it faces across the chasm, then shoot another on the ground of the chasm, way below you. Then jump into the lower portal, and you will soon find yourself shooting out of the wall portal, across the chasm. Of course, almost as much fun as actually completing the game is running through some interesting hypothetical scenarios. I really am just rambling here.

Put one portal on the ceiling, and another on the floor, directly below it. Jump into the floor one, and you'll fall out of the ceiling and into the floor, infinitely many times, moving faster and faster each time. (You can actually do this in the game, and there is apparently some kind of randomization built in that causes you to slightly miss the floor portal after a few iterations. Suppose that didn't happen though.) Suppose you keep your body oriented the normal way. If you look up or down, you see an infinite tunnel of portals, similar to the infinite "hall of mirrors" effect if you stand between two parallel mirrors. Clearly, each time you go through the portal, your kinetic energy is unchanged, but your potential energy increases by your weight times the height of the ceiling. So yes, conservation of energy is being violated, but don't worry about that for now.

As the person goes faster and faster, they measure the distance between the floor and the ceiling to be shrinking, according to special relativity. Eventually, this effect should be so pronounced that, according to the person, two or more parts of the body are at the same place relative to "the" floor. For example, suppose the room has contracted enough that its height is half that of the person. Just as the person's feet are entering the floor portal, his waist is also entering the "previous" floor portal. The person might cite this as evidence that there truly are an infinite number of portals. Meanwhile, an observer sitting quietly in the room would see the portal traveller shrunk to about half his normal height.

I can see that having a basic understanding of special relativity, and almost no understanding of general relativity, is going to be a problem. Still, let's go on. What if the falling portal traveller starts feeling sick, and shoots a portal onto the floor nearby, with the same color as the current floor portal, so they will instantly stop? Putting aside the broken bones and bruises that will likely result, we now have a paradox. If the portal traveller and the stationary observer were both wearing watches, each would have said the other's was running slow. Now that both are in the same frame of reference, which watch has the earlier time, assuming the traveller's watch miraculously didn't break upon impact? Admittedly, no real physical theory should be required to answer this question, as we've already violated conservation of energy, but it's still an interesting thought.

One thing that is completely absent in the game (and probably for good reason) is any significant quantity of liquid. Suppose you have two large tanks. Tank A is full of water, and sits on the ground. Tank B is elevated somewhat, and initially empty. A portal is created that connects the bottom of both tanks. What happens? My first thought is that it works like a siphon, with water "seeking its own level" -- that is, water will flow through the portal, filling tank B, until both tanks have exactly the same water level, relative to the ground. By this logic, if tank A is lifted up after equilibrium is reached, water will again flow from A to B. I can't see why this would happen, so I think a new hypothesis is needed.

One of the first things we learned in PHYS 162 last semester is that electric field lines always diverge from positive charges and converge to negative charges. They never form closed loops, and can only start and end on charges or go out to infinity. Suppose a room contains a single positive charge. If you can trace a field line through a portal, it should come out the corresponding portal, potentially at a different angle. Assume the portals are as in the first situation: one on the ceiling, one on the floor. It seems to me the only way to draw the field lines accurately would have to be by modeling the setup as an infinite set of rooms, stacked one on top of the other, each containing a single positive charge. Further evidence that the portals really do create "copies" of the room, rather than simply connecting two parts of the room which are normally separate.

What if you dropped the positive charge into the portal, the same way we dropped a person through it originally? You would have a moving positive charge, i.e. a current. I suppose this would set up a magnetic field in the room, which would be constantly increasing. If you used two floor portals, instead of a floor and ceiling portal, you would effectively have two nearby AC currents, thus instead of infinite kinetic energy, you could create infinite electromagnetic energy.

I think that's enough for now.