Building Your First Project with Cube2DMCube2DM is a compact, flexible 2D game development framework designed for rapid prototyping and small-to-medium projects. This guide walks you step-by-step through building your first project with Cube2DM: setting up the environment, creating a basic game architecture, implementing core gameplay (player movement, collisions, simple AI), adding assets and sounds, and packaging your project for distribution.
Prerequisites
- Basic familiarity with programming (variables, functions, control flow).
- A development environment: a code editor (VS Code, Sublime, etc.).
- Cube2DM SDK installed (follow the official installation steps for your OS).
- Optional: version control (Git) and a simple graphics editor (Aseprite, GIMP, or Photoshop).
1. Project Setup
-
Create a new project directory:
mkdir cube2dm-first-project cd cube2dm-first-project
-
Initialize the Cube2DM project (replace CLI command if your installed version uses a different one):
cube2dm init
-
Open the project in your editor. Typical folder structure:
- assets/ — images, audio, fonts
- src/ — source code
- scenes/ — scene definitions
- build/ — compiled output
2. Core Architecture
Cube2DM projects typically follow a component-based architecture:
- Entities: game objects (player, enemies, items).
- Components: reusable behaviors (physics, sprite renderer, input).
- Systems: operate on components each frame (rendering, collision detection).
- Scenes: collections of entities and initial settings.
Create a basic file layout:
- src/main.cube (entry point)
- src/player.cube (player entity & logic)
- src/enemy.cube (enemy logic)
- src/systems/physics.cube
- src/systems/render.cube
Example entry point (pseudo-code):
import "scenes/level1" function main() { window.create(800, 600, "Cube2DM Demo") scene.load(level1) loop.run() }
3. Player: Input & Movement
Define a player entity with position, velocity, sprite, and input component.
player.cube (pseudo-code):
entity Player { position: vec2(100, 300) velocity: vec2(0, 0) speed: 200 sprite: Sprite("assets/player.png") collider: BoxCollider(32, 32) } system PlayerControl { onUpdate(dt) { dir = vec2(0, 0) if (input.isDown("left")) dir.x -= 1 if (input.isDown("right")) dir.x += 1 if (input.isDown("up")) dir.y -= 1 if (input.isDown("down")) dir.y += 1 if (dir.length() > 0) dir = dir.normalized() player.velocity = dir * player.speed player.position += player.velocity * dt } }
4. Collisions & Physics
A simple axis-aligned bounding box (AABB) collision system keeps the player from moving through solid tiles or other colliders.
physics.cube:
system Physics { onUpdate(dt) { for each entity with collider and position { // Basic movement resolution & collision checks newPos = entity.position + entity.velocity * dt collisions = world.queryAABB(newPos, entity.collider.size) for each c in collisions { if (c.isSolid) { newPos = resolveCollision(entity, c) } } entity.position = newPos } } }
Collision resolution can be implemented using sweep tests or simple overlap correction.
5. Simple Enemy AI
Create a patrol enemy that moves between two points and reverses direction when reaching the bounds or colliding with walls.
enemy.cube:
entity Enemy { position: vec2(400, 300) speed: 100 dir: 1 patrolMin: 350 patrolMax: 450 sprite: Sprite("assets/enemy.png") collider: BoxCollider(32, 32) } system EnemyAI { onUpdate(dt) { enemy.position.x += enemy.speed * enemy.dir * dt if (enemy.position.x < enemy.patrolMin) enemy.dir = 1 if (enemy.position.x > enemy.patrolMax) enemy.dir = -1 } }
6. Scene & Level Design
Design level tiles and collision layers. Use a simple tilemap format or an external editor (Tiled). Load the tilemap in the scene and instantiate entities.
level1.scene (pseudo-code):
scene Level1 { tilemap: Tilemap("assets/level1.tmx") entities: [ Player, Enemy ] camera: Follow(Player) }
7. Rendering & Camera
A render system draws sprites in correct order (background -> tiles -> entities -> UI). Implement a camera that follows the player with smoothing.
render.cube:
system Render { onRender() { camera.apply() tilemap.draw() for each entity with sprite { sprite.draw(entity.position) } ui.draw() } }
8. Audio & Feedback
Add sound effects for player actions and enemy interactions. Use short WAV/OGG files in assets/audio. Example:
sound.jump = loadSound("assets/audio/jump.ogg") onJump() { sound.play(jump) }
9. UI and HUD
Create a simple HUD showing score and health. Use a bitmap font or system font.
ui.cube:
system UI { onRender() { drawText("Health: " + player.health, vec2(10, 10)) drawText("Score: " + score, vec2(10, 30)) } }
10. Packaging & Distribution
- Build for your target platform:
cube2dm build --platform=windows
- Test on target devices.
- Optionally compress assets and use a simple updater.
Tips & Next Steps
- Use a tile editor (Tiled) for faster level creation.
- Implement an entity pooling system for many enemies/bullets.
- Add more advanced physics (platformer-style collisions, slopes).
- Use Git for version control and branch often.
This walkthrough gives a practical path from empty project to playable demo. Replace pseudo-code with your project’s actual Cube2DM API calls and file formats; the architecture and examples map to most small 2D engines.