Jump to content

  • Log In with Google      Sign In   
  • Create Account

DareDeveloper's Journal



Working on symmetry math issues

Posted by , in Questions And Problems 11 May 2014 - - - - - - · 718 views
javascript, Raid Aces, symmetry and 2 more...
Working on symmetry math issues I am struggling with symmetry math, because I noticed that something was broken (axis symmetry did not work any more, and fixing that broke something else ... or rather revealed that something never actually worked).

The details can be found in a thread:
http://www.gamedev.net/topic/656527-how-do-i-simplify-the-symmetry-math/

I make slow but steady progress on that battlefield.

Since the last screenshot I also changed the height between layers from tile size to 3/4 * the tile size.
The maps are more radable that way, I think, because parts of some covered tiles are exposed.

Posted Image


Isometric View

Posted by , 10 May 2014 - - - - - - · 878 views
Raid Aces, Isometric, JavaScript and 1 more...
Isometric View I render more than just the central map piece now ... and it is now an isometric view.

There are still quite a few problems with it:

I do not wait with rendering until all the images have been loaded: I update the map each time one of the 9 images is loaded.
That means it will render the map several times with errors. Not exactly a bug, that is more like an unimplemented feature, right Posted Image ?

I wanted to render without a grid, but the way I do the seams now does not allow that. I draw edges that lead to stripes in the resulting composed image. I would have to know something about the neighbor landscapes (or have access to the full map) in order to deal with that problem.

Pretty happy with the progress ... next on the list:
  • Actually create items in a scene graph and use it to offer a controllable camera
  • MOBA areas placed in a pseudo random way to get playable maps with bases, jungle spawns, special item spawns, lanes with arenas, sneak paths etc.)
Then I might add the menu game state with GUI entities ...

Posted Image


Lamest progress ever ... working on the foundation

Posted by , in Questions And Problems 07 May 2014 - - - - - - · 663 views
Raid Aces, bugfixing, OOP
Made some changes in the 2D Map creator. I modified the implementation that I had into something that can be used as a superclass.
https://github.com/AndyThiel/raidaces/commit/ac5a18a04c93c0a42371b3da153f3c1433f46a30#diff-018fbfb70ceebe1c7ba76bb10f797e7d

Now game specific implementations can use the foundation and add/modify logic.
Especially the method
CreatorMap2D.prototype.forEachPixelToUpdate
comes in handy now. Iterating over one half of the array depending on the mirroring mode ... being able to reuse that with functions like this one is sweet:
CreatorMap2D.prototype.heightCellularAutomationAction = function(streamSource,
        map, indexX, indexY, mirrorIndexX, mirrorIndexY, neighborTopLeft,
        neighborTopCenter, neighborTopRight, neighborLeft, neighborRight,
        neighborBottomLeft, neighborBottomCenter, neighborBottomRight) {

    var newValueAmount = -1;
    var newValue = -1;

    var currentValueAmount;
    var currentValue;
    for (currentValue = 0; currentValue < 5; currentValue++) {

        currentValueAmount = 0;

        if (currentValue == map.mapArray[indexY][indexX]) {
            currentValueAmount++;
        }
        if (currentValue == neighborTopLeft) {
            currentValueAmount++;
        }
        if (currentValue == neighborTopCenter) {
            currentValueAmount++;
        }
        if (currentValue == neighborTopRight) {
            currentValueAmount++;
        }
        if (currentValue == neighborLeft) {
            currentValueAmount++;
        }
        if (currentValue == neighborRight) {
            currentValueAmount++;
        }
        if (currentValue == neighborBottomLeft) {
            currentValueAmount++;
        }
        if (currentValue == neighborBottomCenter) {
            currentValueAmount++;
        }
        if (currentValue == neighborBottomRight) {
            currentValueAmount++;
        }

        if (newValueAmount < currentValueAmount) {
            newValueAmount = currentValueAmount;
            newValue = currentValue;
        } else if (newValueAmount == currentValueAmount) {
            if (streamSource.consumeBoolean()) {
                newValue = currentValue;
            }
        }
    }

    map.mapArray[indexY][indexX] = newValue;
    map.mapArray[mirrorIndexY][mirrorIndexX] = newValue;

    // if ((map.mapArray.length / 2) == indexY) {
    // log("New height chosen: " + newValue);
    // }
};
I was struggling with yet another bug. The maps were very biased. 0 was used almost exclusively, only at the edges other values had a decent probability. Counting the value of the current tile as well (not just the neighbors) brought the first improvement, dealing with the equal amount of tiles compared with the current maximum count in a pseudo-random way fixed the problem completely. That happens in the following code, taken from the function above:
        } else if (newValueAmount == currentValueAmount) {
            if (streamSource.consumeBoolean()) {
                newValue = currentValue;
            }
        }
I will write a different algorithm (which creates different levels without steep cliffs) soon and update the rendering.

The current state is pretty lame. It can be seen at ...

http://procgames.com/raidaces2/

...though.


Added Symmetry and "Added Performance"

Posted by , 04 May 2014 - - - - - - · 648 views
JavaScript, Raid Aces, Symmetry and 1 more...
Did some optical changes (different heights are suggested) and the maps are now symmetrical (sometimes point, sometimes axis).

http://procgames.com/raidaces/

The StackExchange question helped and my ego is on the verge of being crushed. Basically I let all the timers (25) start at the same time.
That is something that even my little Java concurrency experience should have told me can not be right.
For some reason I thought I could just set the time I want the CPU to be idle with setTimeout.
After I multiplied that time with the image index (0 to 24) it completes faster and it is more responsive, even if it is still a little bumpy.

I need to get better at thinking about what to change and play with when I struggle with this kind of problem.
Stupid brain ...


Introduced GameState Change, new Problem ...

Posted by , in Questions And Problems 03 May 2014 - - - - - - · 727 views
Raid Aces, JavaScript, HTML5 and 4 more...
Created a repository at Github, guess that means I'll stick with the working title for a while.
https://github.com/AndyThiel/raidaces

I decided to commit a lot more in this case and try to really finish and polish it. So far the project was only supposed to be a playground for WebGL experimentation.

There is now a Java project which will at some point offer server side functionality. So far the project can not be built, though ... I just wanted to have a rough structure in place.
It will take some time until I figure out how to bring the technologies together (Ivy, Spring ... probably Jenkins and connections to a database for file storage - maybe CouchDB).

Currently I am working on the client side, though and that probably will not change for quite some time.
The latest big change was trying to move the map / image creation into a gamestate object in order to handle the process asynchronously.
Unfortunately I do not know enough about the lifecycle of those processes and have yet to really think the mechanism through.

What I have right now works mostly in Chrome and sometimes in Firefox (again!) ... but I am not even sure if it works correctly at all.
The loading information is shown, the mouse pointer does not say "busy", but the text can not be selected, so I guess something is still blocking.
Pretty often Firefox blocks everything for almost the entire loading process ...

http://procgames.com/raidaces/

Maybe looking into Closures can help with figuring out what I am doing and what I should be doing.

EDIT:
I asked the question on StackExchange:
http://programmers.stackexchange.com/questions/237863/how-can-i-fix-blocking-javascript-processes

A feeling tells me that the process is called asynchronously but still blocks everything, because the CPU works on the new process exclusively.
Maybe I have to use several setTimeout calls in order to free CPU resources (so that the tab / browser is never blocked)!?


Found the drawImage problem ...

Posted by , in Questions And Problems 22 April 2014 - - - - - - · 894 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 - - - - - - · 726 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 - - - - - - · 503 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