The first screenshot of Infiniworld!
Welcome back, fellow web traveler. Here is, as I promised you in my previous post, the very first screenshot of Infiniworld.
- Spawn your very own blocky creatures with a single key stroke (Enter/Return) !
- Take control of your creatures and tell them where to go (WASD keys to move) !
- A stunningly fluid 60 FPS refresh rate on any recent machine !
- Save your battery life: the game sleeps when it has nothing to do !
- Spy on yourself by logging everything you do into a file, and learn about what’s going on under the hood !
Game does not feature:
- Physics engine.
- Any kind of landscape.
- Boobies and explosions (Actually they are in game, but only allegorically, just use your imagination).
- Things to do.
Download and play this first interactive version of Infiniworld !
GitHub link: https://github.com/Niriel/Infiniworld/tree/v0.0.2
If you are a git user:
git clone email@example.com:Niriel/Infiniworld.git
If you just want a zip:
- Go there : https://github.com/Niriel/Infiniworld/
- Click on the big “Downloads” button on the right of the screen.
- A window appears. Under “Download Packages”, click on v0.0.2.
- That’s it, you have the zip !
Run the game.
Enter the src directory and type “python solo.py”.
How does it all work ? you ask. Here is how:
- Model classes: WorldModel, EntityModel.
- View classes: PygameView, AreaView, EntityView.
- Controller classes: PygameController, PlayerController, GameLoopController.
The world is extremely simple for now. There is no landscape, no map, no tiles. It contains nothing but some entities. I call “entity” anything that exists in the game world and can move: creatures, fireballs…
Entities are represented by an EntityModel class and have a position stored as a two-dimensional vector (see geometry.Vector). Each EntityModel has a unique entity_id. Every event regarding a given entity will carry that entity_id. Today, the role of the EntityModel is to change its position when it is asked to do so. Since there is no landscape and no physics engine, it always accept any order it receives. That means that any MoveEntityRequest results in a EntityMovedEvent.
For now, the only responsibilities of WorldModel are to create and destroy EntityModel instances, and keep a list of them.
The PygameView is the root of everything that is displayed on the screen. It opens the window and draws everything that needs to be drawn when it receives a RenderFrameEvent.
The AreaView displays a part of the world: landscape, entities. There is no landscape so it just displays entities for now. Each time AreaView receives an EntityCreatedEvent, it instantiates an EntityView object for representing it.
EntityView objects listen to the EntityMovedEvents to remain in sync with the EntityModel objects.
These views uses pygame.sprite for showing themselves on the screen. The sprites of the EntityViews objects are blitted onto the sprite of the AreaView object, which is blitted onto the display by PygameView. On the screenshot, the display is black, the AreaView is gray and the EntityViews are white.
The PygameController translates the pygame events (which are SDL events) into Infiniworld events. For example, it translates the fact that Escape key is pressed into a QuitEvent.
The PlayerController contains an entity_id: the entity being controlled by the player. When the PlayerController receives a PlayerMovedEvent from the PygameController, it responds by posting a MoveEntityRequest with the proper entity_id.
The last controller is the GameLoopController. The current implementation is pretty naive and simple. It posts a ProcessInputsEvent and a RenderFrameEvent 60 times per second. ProcessInputEvent wakes up the PygameController and RenderFrameEvent wakes up the PygameView. Note that the GameLoopController does not use any pygame function, so it does not call pygame.time.clock for running at 60 FPS. Instead, it uses the time module from the standard library. The game loop stops when the GameLoopController receives a QuitEvent.
What next ?
The goal of this demo was to have something interactive as quickly as I could. It works: I can create entities and move them around. But it’s not pretty: the entities are teleported, it is not fluid at all. It would be nice to have a physics engine. However, a physics engine should manage collisions, and I do not have much to collide against for now. I need a landscape. So I think that the next step is to implement tiles, maps, areas, etc..
The WorldModel will hold many AreaModel instances in memory: dungeons floors, cities, overworld, etc.. The EntityModel needs to be extended to accomodate the fact that there are now several areas. The AreaView should show one area only. Entities should be able to move from one area to another. Lots of work to do !