Jump to content

  • Log In with Google      Sign In   
  • Create Account

DareDeveloper's Journal



Found the drawImage problem ...

Posted by , in Questions And Problems 22 April 2014 - - - - - - · 890 views
drawImage, HTML5, canvas, Firefox and 1 more...
Found the bug I wrote about in the last post: drawImage worked in Chrome, but Firefox showed a white image.
http://www.procgames.com/raidaces

I was completely on the wrong track when I noticed that it sometimes works in Firefox when I call the update function after waiting 5 seconds.

What surprised me was that every time it worked it rendered images with only brown tiles, so I abandoned that track (well, also because waiting 20seconds did not improve the odds at all).
Because I am really ... and I mean REALLY bad at google searches I suspected color profiles (hey, they were mentioned in a canvas related stackexchange discussion ... Posted Image along with green pixels ... can that be a coincidence?).

When I ruled those out I suspected caching ... that it somehow managed to render the all brown tiles images because one of them was cached at some point.
I confirmed that caches did play a role by using the reproducible way to generate maps. After a refresh, drawImage always worked and sometimes it even showed an old version of an image (not from the current map).

Of course it turned out to be the obvious thing. I need to wait for the load event of the image before I draw it to the canvas.
It is not that this thought had not crossed my mind right away when the error occurred ... for some reason I thought that was not relevant ... probably because I expected images to be transferred from canvas to img elements immediately - and in this case synchronously.

In hindsight it makes sense that the normal rules apply. After all, the image data is read using a dataURL. Posted Image


Scope Problem ... maybe?

Posted by , in Project Ideas 20 April 2014 - - - - - - · 657 views
project, procedural and 3 more...
Hi all,

after abandoning the simple game, I may have started something HUGE ... as in: a little too big as the next step, considering that it is just another "getting familiar with XYZ" project.

Eventually I want to create level, normal and depth maps through pcg methods and use WebGL & shaders for interesting 2D lighting effects.
It is not that there is no progress. I think what I have so far has potential ... but there are quite a few battles that need to be fought.
  • A map with 256 x 256 tiles is created randomly (so far the array stores values 0 and 1 only)
  • Cellular automation is used to get a smooth result
  • A landscape creator serves as a cursor into the map and it translates the map into renderable chunks
  • 25 x 3 images are rendered (map areas around the players position), so far only the level map is drawn in a very basic way, normal and depth map stay white.
  • So far the contexts are still 2D canvas contexts. A part of the landscape at the center is copied to the main canvas.
http://procgames.com/raidaces/

For some reason Firefox does not do the last part: transfer the image to the main canvas.
It does work for me in Chrome. Not sure if that is a bug in my code ... there is no error message shown by Firebug.

At least I know now that my Java approach with stream sources works in JavaScript as well:

For reproducible content:
var MIN_SEQUENCE_LENGTH = 40;
var MAX_SEED_VALUE = 123321;

//
// StreamSourceFixed
//
function StreamSourceFixed(seed1, seed2) {
	this.currentNumber1 = seed1;
	this.currentNumber2 = seed2;
	this.bufferSequence = "";
}

StreamSourceFixed.prototype = Object.create(AbstractStreamSource.prototype);
StreamSourceFixed.prototype.constructor = StreamSourceFixed;

//
// Methods
//

StreamSourceFixed.prototype.consumeChar = function() {
	return String.fromCharCode(this.consumeByte());
}

StreamSourceFixed.prototype.consumeByte = function() {
	this.updateBufferSequence();
	var number = parseInt(this.bufferSequence.substring(0,3)) % 256;
	this.bufferSequence = this.bufferSequence.substring(3);
	return number;
}

StreamSourceFixed.prototype.consumeShort = function() {
	this.updateBufferSequence();
	var number = parseInt(this.bufferSequence.substring(0,5)) % 32768;
	this.bufferSequence = this.bufferSequence.substring(5);
	return number;
}

StreamSourceFixed.prototype.consumeInt = function() {
	this.updateBufferSequence();
	var number = parseInt(this.bufferSequence.substring(0,10)) % 2147483648;
	this.bufferSequence = this.bufferSequence.substring(10);
	return number;
}

StreamSourceFixed.prototype.consumeLong = function() {
	this.updateBufferSequence();
	var number = parseInt(this.bufferSequence.substring(0,16)) % 9007199254740993;
	this.bufferSequence = this.bufferSequence.substring(16);
	return number;
}

StreamSourceFixed.prototype.consumeDouble = function() {
	throw "error_double_not_supported";
}

StreamSourceFixed.prototype.consumeBoolean = function() {
	this.updateBufferSequence();
	var number = parseInt(this.bufferSequence.substring(0, 1)) % 2;
	this.bufferSequence = this.bufferSequence.substring(1);
	return 1 == number;
}

StreamSourceFixed.prototype.updateBufferSequence = function() {
	while (MIN_SEQUENCE_LENGTH > this.bufferSequence.length) {

		this.bufferSequence += this.currentNumber1;
		this.bufferSequence += this.currentNumber2;
		
		var sum = (this.currentNumber1 + this.currentNumber2);
		while (MAX_SEED_VALUE < sum) {
			sum -= MAX_SEED_VALUE;
		}

		this.currentNumber1 = this.currentNumber2;
		this.currentNumber2 = sum;
	}
}

... and the random one:
//
// StreamSourceRandom
//
function StreamSourceRandom() {
	StreamSourceFixed.apply(this, [
		Math.floor((Math.random()*MAX_SEED_VALUE)+1),
		Math.floor((Math.random()*MAX_SEED_VALUE)+1)
	]);
}

StreamSourceRandom.prototype = Object.create(StreamSourceFixed.prototype);
StreamSourceRandom.prototype.constructor = StreamSourceRandom;




I'll call it a game ...

Posted by , 13 April 2014 - - - - - - · 724 views
Tetris, 2048, Canvas, HTML5 and 1 more...
Here it is: http://www.procgames.com/demos4/notprocatall.html (might have seen that coming if you saw the last journal entry...)


Well, it is anything but finished ... only in the sense that I will not work on it any longer ... and it is buggy as hell.
I implemented the recursive trickling of merged tiles the ugly way ... and I did add
  • the removal of full rows (as a way to deal with low numbers under higher ones)
  • score counter
  • and a game over screen (which has a hard time showing up but it usually does eventually).
I would feel bad, because giving up is not a habit I should get into, but I think I can make a strong case for investing energy elsewhere:

1.) I am not turning this into a habit. I work as a programmer and I have to search for bugs and work on the same code for weeks or month. The resilience is there, working on this project would only be a nuisance.
2.) I have reached the goals:
  • I know how to use the cavas now
  • I have done something with JavaScript ... I even used some OO, even if the code is pretty bad
  • What I have gives a nice enough impression of what a combination of the game mechanics feels like
3.) If this idea can be turned into a real game it would take a lot of time and effort to find out how ... a lot more than just working on the game a few more days.
4.) It is not something that people are interested in. Hopefully nobody will study the code. People also apparently don't want to see a tutorial about basic games (http://www.gamedev.net/topic/654740-what-are-you-interested-in/?mode=show)
5.) It has nothing to do with procedural content generation ... which is what is currently occupying my mind. My heart is not in the project ...


So what is next?:
probably some more HTML5 / JavaScript experiments, this time with WebGL and without letting the code rot as much.

You reached level 7 with 3787216 points.




Trickier than I thought

Posted by , 10 April 2014 - - - - - - · 501 views
Tetris, 2048, JavaScript, HTML5
Combining the logic of Tetris and 2048 is trickier than I thought.

Not even figuring out what I want the program to do ...
the logic gets more and more complex and the special cases are a nuisance.

What I have so far is tiles that can penetrate tiles with the same number, tiles that merge when a block collides while same-number-tiles are on top of each other ...

http://www.procgames.com/demos/notprocatall.html

... and the beginning of freshly merged tiles staying active.

http://www.procgames.com/demos2/notprocatall.html

The biggest problem is the approach I picked:
the current block is modified and contains only the merged tiles, while the other tiles (collided ones and numbers that are not stacked) are put into the game field and stay stationary.

The remaining block keeps moving as long as it does not collide, but that is still too strict.
The tiles should trickle down independently until all of them have collided.

I thought using the existing block collision method was a smart thing to do, because I want the player to have control over the new pseudo-block.
That would be doable, but the problem is that within a round there should be several collision tests now (will the merged tile move in the next round, or is it not alive any more?) ... which really does not quite fit ...
GameStateDefault.prototype.update = function(gameContext) {

	this.isMovingBlocked = false;
	this.frameAge += this.getFrameDuration();

	if (this.frameAge > this.getTurnDuration()) {

		this.frameAge = 0;

		this.handleNextTurnEvent(gameContext);
		this.copyFieldToCanvas();
		this.copyBlockToCanvas();

		gameContext.clearRect(0,0,640,500);
		gameContext.fillStyle = "#edc22e";
		gameContext.font = "bold 20px Arial";

		// this.gameplayField.draw(gameContext);
		// this.gameplayBlock.draw(gameContext);

		var indexX;
		var indexY;
		for (indexY = 0; indexY < this.fieldHeight; indexY++) {
			for (indexX = 0; indexX < this.fieldWidth; indexX++) {
				this.drawTileAndMerges(this.getXOffset(), 0, indexX, indexY, this.canvasArray[indexY][indexX], this.mergeArray[indexY][indexX], gameContext);
			}
		}

		this.previewBlock.drawAt(this.getXOffset() + (this.gameplayField.width * this.getTilesize()) + 10, 10, gameContext);
	}

	this.frameCount++;
}
...
GameStateDefault.prototype.checkForCollisions = function(gameContext) {

	// var message = "this.gameplayBlock.isRigid: " + this.gameplayBlock.isRigid;

	// var aliveCount = 0;

	var blockPosX = this.gameplayBlock.posX;
	var newBlockPosY = this.gameplayBlock.posY + 1;
	var gameplayBlockArray = this.gameplayBlock.blockArray;

	var indexX;
	var indexY;
	for (indexY = 0; indexY < gameplayBlockArray.length; indexY++) {

		var fieldIndexY = this.gameplayBlock.posY + indexY;

		for (indexX = 0; indexX < gameplayBlockArray.length; indexX++) {

			var fieldIndexX = this.gameplayBlock.posX + indexX;

			if (TILETYPE_NONE != gameplayBlockArray[indexY][indexX]) {
				if (this.fieldHeight <= (newBlockPosY + indexY)) {
					//if (this.gameplayBlock.isRigid) {
						return 1;
					//} else {
						//this.gameplayField.gameArray[fieldIndexY][fieldIndexX] = gameplayBlockArray[indexY][indexX];
						//gameplayBlockArray[indexY][indexX] = TILETYPE_NONE;
					//}
				} else {
					if (TILETYPE_NONE != this.gameplayField.gameArray[newBlockPosY + indexY][blockPosX + indexX]) {
						if (gameplayBlockArray[indexY][indexX] != this.gameplayField.gameArray[newBlockPosY + indexY][fieldIndexX]) {

							//if (this.gameplayBlock.isRigid) {
								return 1;
							//} else {
								//if (this.gameplayField.gameArray[fieldIndexY][fieldIndexX] == gameplayBlockArray[indexY][indexX]) {
								//	gameplayBlockArray[indexY][indexX] *= 2;
								//	this.gameplayField.gameArray[fieldIndexY][fieldIndexX] = TILETYPE_NONE;
								//	aliveCount++;
								//} else {
								//	gameplayBlockArray[indexY][indexX] = TILETYPE_NONE;
								//	this.gameplayField.gameArray[fieldIndexY][fieldIndexX] = gameplayBlockArray[indexY][indexX];
								//}
							//}
						//} else {
							//aliveCount++;
						}
					}
				}
			}
		}
	}

	// showMessage(message);

	//if ((false == this.gameplayBlock.isRigid) && (0 == aliveCount)) {
		//return 1;
	//}

	return 0;
}
...
GameStateDefault.prototype.handleMerges = function(gameContext) {

	var mergeCount = 0;

	var gameplayBlockArray = this.gameplayBlock.blockArray;
	// var activeTilesBlockArray = this.activeTilesBlock.blockArray;
	// this.activeTilesBlock.posX = this.gameplayBlock.posX;
	// this.activeTilesBlock.posY = this.gameplayBlock.posY;

	var indexX;
	var indexY;
	for (indexY = 0; indexY < gameplayBlockArray.length; indexY++) {

		for (indexX = 0; indexX < gameplayBlockArray.length; indexX++) {
			if (gameplayBlockArray[indexY][indexX] != TILETYPE_NONE) {
				if (gameplayBlockArray[indexY][indexX] != this.gameplayField.gameArray[this.gameplayBlock.posY + indexY][this.gameplayBlock.posX + indexX]) {
					this.gameplayField.gameArray[this.gameplayBlock.posY + indexY][this.gameplayBlock.posX + indexX] = gameplayBlockArray[indexY][indexX];
					gameplayBlockArray[indexY][indexX] = TILETYPE_NONE;
				} else {
					this.gameplayField.gameArray[this.gameplayBlock.posY + indexY][this.gameplayBlock.posX + indexX] = TILETYPE_NONE;
					gameplayBlockArray[indexY][indexX] = (2 * gameplayBlockArray[indexY][indexX]);
					this.gameplayBlock.isRigid = false;
					mergeCount++;
				}
			}
		}
	}

	return mergeCount;
}
The weekend is approaching, though ... so I am confident that I will think of something ... soon enough Posted Image


Getting to know the Canvas

Posted by , in Project Ideas 02 April 2014 - - - - - - · 651 views
Canvas, HTML, JavaScript, Tetris and 1 more...
I am familiarizing myself with JS and HTML5, Canvas first ... not WebGL yet.

The first thing I am trying to do is programming what I had in mind when I heard that there is a combination between Tetris and 2048.
Not sure if the game mechanics will make a lick of sense, but I want to know what it feels like.

Working Title: NPAA (Not Proc At All)

I have not managed to keep the code clean, so I will have to refactor soon.
I also need to look at articles about object oriented programming in JS.
What I have so far are procedures, procedures, global constants and variables and ... procedures ... and already the if/else statements annoy me.

So far I can cycle through the different block types and their rotations (with the arrow keys).
The delayed response to the user action is a feature, not a bug btw. Posted Image
In the actual gameplay the response will be immediate.

The next step will either be writing some ugly gameplay logic ... or researching and refactoring.

Posted Image







PARTNERS