[AS3] Level design/parralax scrolling

Subscribe to [AS3] Level design/parralax scrolling 2 posts

avatar for Kim_Bo Kim_Bo 21 posts
Flag Post

Hi i am making game, and most of the graphic elements are ready now, but still having programing issues.

I dont know how to design pattern for level manager. Each of my levels is build in different way one have only 1 layer (floating background), one 3 layers (move able background, collision lines, and light effects- all 3 with same speed) and other level for example 6 ( static background, background, collision lines, parallax background 1, parallax background 2).
How to make a manager for this kind of levels. Where to put collision detection (in game class, player class or what)
Is there any ready to implement source code for that?? Would use Vcam, but i really don’t know how it works
Now i am just adding speed variable to player’s x position. When players.x > than something player speed = 0, and start adding same speed to background…

I am really new to OOP so i will be really appreciate for helping with those problems :)

 
avatar for BobJanova BobJanova 858 posts
Flag Post

A good starting point for design is to look at the nouns you used and see if they make sense as classes, and what the links are. You don’t need all of them necessarily but it’s a good starting point.

So let’s see. You have ‘level’, ‘background’ (floating, movable, static, parallax), ‘layer’, ‘effects’ (including collision lines there since if I understand correctly it’s an effect) and ‘collision detection’. I assume that there are also ‘game objects’ or ‘entities’, since otherwise there is no game! (These would be things like your character, item drops, projectiles, and enemies.)

Typically collision detection is done at the ‘in-play level’ degree of abstraction. That is, an in-play level (which consists of a level definition, currently active entities and state information like score and lives) would be running the main game loop, advancing characters due to movement controls and the like, and that is where you should put collision detection. That’s because collisions occur between entities, and therefore you need to be in the context that includes all the entities you need to look at. You haven’t talked about the entity structure you’re using so it’s hard to be specific here. For example here’s a simple level update loop modified from my platform engine:

	public function Update(ticks:Number) : void {
	if (this.ticks == 0) {
		for each(var e:Entity in entities) e.StartLevel();
	}
	
	this.ticks += ticks;
	
	
	if (success || playerCharacter.dead) {
		gameOver = true;
		gameOverTicks += ticks;
	}

	// Many loops in here: move and update, 
	// then garbage collect, then collision resolution			
	var ex:Number, ey:Number;
	
	// MOVE AND UPDATE
	for (var i:int = 0; i < entities.length; i++) {
		e = entities[i];
		e.level = this;
		if (ShouldKill(e)) e.dead = true;
		if(!e.dead) e.UpdateEntity(this, ticks);
		e.collided = false;
	}
	
	// GARBAGE COLLECT
	for (i = entities.length - 1; i >= 0;  i--) {
		e = entities[i];
		if (e.dead) {
			e.level = null;
			entities.splice(i, 1);
			EntityDeath(e);
		}
	}
	
	// COLLISION DETECTION/RESOLUTION
	for (i = 0; i < entities.length; i++) {
		e = entities[i];
		ex = e.location.x - scrollx; ey = e.location.y - scrolly;
		if (e.Hull) {
			for (var j:int = i + 1; j < entities.length; j++) {
				var e2:Entity = entities[j];
				ex = e2.location.x - scrollx; ey = e2.location.y - scrolly;
				if (!(e2.Hull && (e.mobile || e2.mobile))) continue;
				var cr:CollisionResponse = e.Hull.Collides(e2.Hull);
				if (cr != null) {
					e.collided = e.CollisionResponse(e2, cr) || e.collided;
					cr.CVec.Multiple( -1, true);
					e2.collided = e2.CollisionResponse(e, cr) || e2.collided;
					Collision(e, e2, cr);
				}
			}
		}
	}
	
	// DISPLAY UPDATE
	scrollx = UpdateScrollX(scrollx, ticks);
	scrolly = UpdateScrollY(scrolly, ticks);
}

Now, you don’t have to follow the code exactly, but hopefully you can see that collision detection is done where the rest of the entity movement is done.

Let’s go back to the background issue. Backgrounds are a graphical feature of a level, so let’s have a container called GraphicalEffects or something, and let’s see how those nouns we picked out earlier work out.

Here’s what I picked out of your text regarding backgrounds (excluding ‘level’ now): ‘background’ (floating, movable, static, parallax), ‘layer’, ‘effects’ (including collision lines there since if I understand correctly it’s an effect). The parentheses already indicate grouping and subclasses. This looks like a hierarchy!

Background
 - FloatingBackground
 - MovableBackground
 - StaticBackground
 - ParallaxBackground
Layer
Effect
 - CollisionLine

If we read your description more carefully it seems like you actually confused ‘background’ and ‘layer’, and what you probably actually mean is this:

Background: has zero or more Layers, and 0 or more Effects
Layer: can display itself, and needs to be updated with the game timer (like an entity)
 - StaticBackground: displays a single fixed image
 - FloatingBackground: not quite sure what this is
 - MovableBackground: can be moved based on game events
 - ParallaxBackground: moves in a particular way
Effect: can display itself, and is updated based on game events
 - CollisionLine: displays the results of a collision

And now if we look at that, we see that Layers and Effects are actually very similar! So let’s make them a subclass of a generic self-drawing graphical item. (And they both share a feature with Entity, so if it fits into your current structure, you want Entity included in there too, with the updating-based-on-timer as a common function.) Also note that the Parallax (and maybe Floating) background sounds like a subset of the Movable one. So my final sketch would be:

Background: has zero or more Layers, and 0 or more Effects
GraphicalItem: can display itself, and needs to be updated with the game timer (like an entity)
 - Layer: draws over the whole screen as a background item
   - StaticBackground: displays a single fixed image
   - FloatingBackground: not quite sure what this is
   - MovableBackground: can be moved based on game events
     - ParallaxBackground: moves in a particular way
 - Effect: can display itself, and is updated based on game events
   - CollisionLine: displays the results of a collision

(Of course, a Level, not shown here, has a Background and that’s how we get this hooked up to the code at all.)

Only once you’ve got to this point, where you’ve drawn out the classes you want and the interactions between them (at least in sketch form), should you hit the code. Now let’s turn that sketch into skeletal code, since you are new and this might help you. Note that what is in this code block is almost equivalent to the English text tree just above.

class Background {
 var layers:Vector.<Layer>;
 var effects:Vector.<Effect>;

 public function draw(level:Level) : void {
  for(var layer:Layer in layers) layer.draw(level);
  for(var effects:Effect in effects) effect.draw(level);
 }
}

class GraphicalItem { // note: this should extend something common with Entity too
 public function draw(level:Level) {
  // some code here to hit the screen, which depends on how you do that already
 }
}

class Layer extends GraphicalItem {
 // so far, we don't have anything special to go here in code, but you will when you start filling out
}

class StaticLayer extends Layer {
 public override function draw(level:Level) {
  // draw an image here
 }
}

class MovableLayer extends Layer {
 protected var x:int, y:int;

 public override function draw(level:Level) {
  // draw an image here offset by x, y
 }
}

class ParallaxLayer extends MovableLayer {
 private var parallaxFactor:Number = 2f;
 public override function draw(level:Level) {
  x = level.x / parallaxFactor; y = level.y / parallaxFactor;
  // draw an image here
 }
}

// ... etc for effects