From dc06cab69f9e871aa8f7f519c964cf632d2217ea Mon Sep 17 00:00:00 2001 From: Jules Date: Thu, 10 Nov 2016 15:34:53 -0500 Subject: meatheadz --- jquery.gamequery-0.5.1.js | 1164 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1164 insertions(+) create mode 100755 jquery.gamequery-0.5.1.js (limited to 'jquery.gamequery-0.5.1.js') diff --git a/jquery.gamequery-0.5.1.js b/jquery.gamequery-0.5.1.js new file mode 100755 index 0000000..07b81ee --- /dev/null +++ b/jquery.gamequery-0.5.1.js @@ -0,0 +1,1164 @@ +/* + * gameQuery rev. 0.5.1 + * + * Copyright (c) 2008 Selim Arsever (gamequery.onaluf.org) + * licensed under the MIT (MIT-LICENSE.txt) + */ +// this allow to used the convenient $ notation in a plugins +(function($) { + + $.extend({ gameQuery: { + /** + * This is the Animation Object + */ + Animation: function (options) { + // private default values + var defaults = { + imageURL: "", + numberOfFrame: 1, + delta: 0, + rate: 30, + type: 0, + distance: 0, + offsetx: 0, + offsety: 0 + }; + + // options extends defaults + options = $.extend(defaults, options); + + //"public" attributes: + this.imageURL = options.imageURL; // The url of the image to be used as an animation or sprite + this.numberOfFrame = options.numberOfFrame;// The number of frame to be displayed when playing the animation + this.delta = options.delta; // The the distance in pixels between two frame + this.rate = options.rate; // The rate at which the frame must be played in miliseconds + this.type = options.type; // The type of the animation.This is bitwise OR of the properties. + this.distance = options.distance; // The the distance in pixels between two animation + this.offsetx = options.offsetx; // The x coordinate where the first sprite begin + this.offsety = options.offsety; // The y coordinate where the first sprite begin + + //Whenever a new animation is created we add it to the ResourceManager animation list + $.gameQuery.resourceManager.addAnimation(this); + + return true; + }, + + // "constants" for the different type of an animation + ANIMATION_VERTICAL: 1, // genertated by a verical offset of the background + ANIMATION_HORIZONTAL: 2, // genertated by a horizontal offset of the background + ANIMATION_ONCE: 4, // played only once (else looping indefinitly) + ANIMATION_CALLBACK: 8, // A callack is exectued at the end of a cycle + ANIMATION_MULTI: 16, // The image file contains many animations + + // "constants" for the different type of geometry for a sprite + GEOMETRY_RECTANGLE: 1, + GEOMETRY_DISC: 2, + + // basic values + refreshRate: 30, + + /** + * An object to manages the resources loading + **/ + resourceManager: { + animations: [], // List of animation / images used in the game + sounds: [], // List of sounds used in the game + callbacks: [], // List of the functions called at each refresh + running: false, // State of the game, + + /** + * This function the covers things to load befor to start the game. + **/ + preload: function() { + //Start loading the images + for (var i = this.animations.length-1 ; i >= 0; i --){ + this.animations[i].domO = new Image(); + this.animations[i].domO.src = this.animations[i].imageURL; + } + + //Start loading the sounds + for (var i = this.sounds.length-1 ; i >= 0; i --){ + this.sounds[i].load(); + } + + $.gameQuery.resourceManager.waitForResources(); + }, + + /** + * This function the waits for all the resources called for in preload() to finish loading. + **/ + waitForResources: function() { + var loadbarEnabled = ($.gameQuery.loadbar != undefined); + if(loadbarEnabled){ + $($.gameQuery.loadbar.id).width(0); + var loadBarIncremant = $.gameQuery.loadbar.width / (this.animations.length + this.sounds.length); + } + //check the images + var imageCount = 0; + for(var i=0; i < this.animations.length; i++){ + if(this.animations[i].domO.complete){ + imageCount++; + } + } + //check the sounds + var soundCount = 0; + for(var i=0; i < this.sounds.length; i++){ + var temp = this.sounds[i].ready(); + if(temp){ + soundCount++; + } + } + //update the loading bar + if(loadbarEnabled){ + $("#"+$.gameQuery.loadbar.id).width((imageCount+soundCount)*loadBarIncremant); + if($.gameQuery.loadbar.callback){ + $.gameQuery.loadbar.callback((imageCount+soundCount)/(this.animations.length + this.sounds.length)*100); + } + } + if($.gameQuery.resourceManager.loadCallback){ + var percent = (imageCount+soundCount)/(this.animations.length + this.sounds.length)*100; + $.gameQuery.resourceManager.loadCallback(percent); + } + if(imageCount + soundCount < (this.animations.length + this.sounds.length)){ + imgWait=setTimeout(function () { + $.gameQuery.resourceManager.waitForResources(); + }, 100); + } else { + // all the resources are loaded! + // We can associate the animation's images to their coresponding sprites + $.gameQuery.sceengraph.children().each(function(){ + // recursive call on the children: + $(this).children().each(arguments.callee); + // add the image as a background + if(this.gameQuery && this.gameQuery.animation){ + $(this).css("background-image", "url("+this.gameQuery.animation.imageURL+")"); + // we set the correct kind of repeat + if(this.gameQuery.animation.type & $.gameQuery.ANIMATION_VERTICAL) { + $(this).css("background-repeat", "repeat-x"); + } else if(this.gameQuery.animation.type & $.gameQuery.ANIMATION_HORIZONTAL) { + $(this).css("background-repeat", "repeat-y"); + } else { + $(this).css("background-repeat", "no-repeat"); + } + } + }); + + // And launch the refresh loop + $.gameQuery.resourceManager.running = true; + setInterval(function () { + $.gameQuery.resourceManager.refresh(); + },($.gameQuery.refreshRate)); + if($.gameQuery.startCallback){ + $.gameQuery.startCallback(); + } + //make the sceengraph visible + $.gameQuery.sceengraph.css("visibility","visible"); + } + }, + + /** + * This function refresh a unique sprite here 'this' represent a dom object + **/ + refreshSprite: function() { + //Call this function on all the children: + // is 'this' a sprite ? + if(this.gameQuery != undefined){ + var gameQuery = this.gameQuery; + // does 'this' has an animation ? + if(gameQuery.animation){ + //Do we have anything to do? + if(gameQuery.idleCounter == gameQuery.animation.rate-1){ + // does 'this' loops? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_ONCE){ + if(gameQuery.currentFrame < gameQuery.animation.numberOfFrame-2){ + gameQuery.currentFrame++; + } else if(gameQuery.currentFrame == gameQuery.animation.numberOfFrame-2) { + gameQuery.currentFrame++; + // does 'this' has a callback ? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_CALLBACK){ + if($.isFunction(gameQuery.callback)){ + gameQuery.callback(this); + } + } + } + } else { + gameQuery.currentFrame = (gameQuery.currentFrame+1)%gameQuery.animation.numberOfFrame; + if(gameQuery.currentFrame == 0){ + // does 'this' has a callback ? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_CALLBACK){ + if($.isFunction(gameQuery.callback)){ + gameQuery.callback(this); + } + } + } + } + // update the background: + if(gameQuery.animation.type & $.gameQuery.ANIMATION_VERTICAL){ + if(gameQuery.multi){ + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.multi)+"px "+(-gameQuery.animation.offsety-gameQuery.animation.delta*gameQuery.currentFrame)+"px"); + } else { + $(this).css("background-position",""+(-gameQuery.animation.offsetx)+"px "+(-gameQuery.animation.offsety-gameQuery.animation.delta*gameQuery.currentFrame)+"px"); + } + } else if(gameQuery.animation.type & $.gameQuery.ANIMATION_HORIZONTAL) { + if(gameQuery.multi){ + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.animation.delta*gameQuery.currentFrame)+"px "+(-gameQuery.animation.offsety-gameQuery.multi)+"px"); + } else { + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.animation.delta*gameQuery.currentFrame)+"px "+(-gameQuery.animation.offsety)+"px"); + } + } + } + gameQuery.idleCounter = (gameQuery.idleCounter+1)%gameQuery.animation.rate; + } + } + return true; + }, + + /** + * This function refresh a unique tile-map here 'this' represent a dom object + **/ + refreshTilemap: function() { + //Call this function on all the children: + // is 'this' a sprite ? + if(this.gameQuery != undefined){ + var gameQuery = this.gameQuery; + if($.isArray(gameQuery.frameTracker)){ + for(var i=0; i= 0; i--){ + if(this.callbacks[i].idleCounter == this.callbacks[i].rate-1){ + var returnedValue = this.callbacks[i].fn(); + if(typeof returnedValue == 'boolean'){ + // if we have a boolean: 'true' means 'no more execution', 'false' means 'execute once more' + if(returnedValue){ + deadCallback.push(i); + } + } else if(typeof returnedValue == 'number') { + // if we have a number it re-defines the time to the nex call + this.callbacks[i].rate = Math.round(returnedValue/$.gameQuery.refreshRate); + this.callbacks[i].idleCounter = 0; + } + } + this.callbacks[i].idleCounter = (this.callbacks[i].idleCounter+1)%this.callbacks[i].rate; + } + for(var i = deadCallback.length-1; i >= 0; i--){ + this.callbacks.splice(deadCallback[i],1); + } + }, + + addAnimation: function(animation) { + if($.inArray(animation,this.animations)<0){ + //normalize the animationRate: + animation.rate = Math.round(animation.rate/$.gameQuery.refreshRate); + if(animation.rate==0){ + animation.rate = 1; + } + this.animations.push(animation); + } + }, + + addSound: function(sound){ + if($.inArray(sound,this.sounds)<0){ + this.sounds.push(sound); + } + }, + + + registerCallback: function(fn, rate){ + rate = Math.round(rate/$.gameQuery.refreshRate); + if(rate==0){ + rate = 1; + } + this.callbacks.push({fn: fn, rate: rate, idleCounter: 0}); + } + }, + + // This is a single place to update the underlying data of sprites/groups/tiles + update: function(descriptor, transformation) { + // Did we really recieve a descriptor or a jQuery object instead? + if(!$.isPlainObject(descriptor)){ + // Then we must get real descriptor + if(descriptor.length > 0){ + var gameQuery = descriptor[0].gameQuery; + } else { + var gameQuery = descriptor.gameQuery; + } + } else { + var gameQuery = descriptor; + } + // If we couldn't find one we return + if(!gameQuery) return; + if(gameQuery.tileSet === true){ + //then we have a tilemap! + descriptor = $(descriptor); + // find the tilemap offset relatif to the playground: + var playgroundOffset = $.gameQuery.playground.offset(); + var tileSetOffset = descriptor.offset(); + tileSetOffset = {top: tileSetOffset.top - playgroundOffset.top, left: tileSetOffset.left - playgroundOffset.left}; + // test what kind of transformation we have and react accordingly: + // Update the descriptor + for(property in transformation){ + switch(property){ + case "left": + //Do we need to activate/desactive the first/last column + var left = parseFloat(transformation.left); + //Get the tileSet offset (relatif to the playground) + var playgroundOffset = $.gameQuery.playground.offset(); + var tileSetOffset = descriptor.parent().offset(); + tileSetOffset = {top: tileSetOffset.top - playgroundOffset.top, left: tileSetOffset.left + left - playgroundOffset.left}; + + //actvates the visible tiles + var firstColumn = Math.max(Math.min(Math.floor(-tileSetOffset.left/gameQuery.width), gameQuery.sizex),0); + var lastColumn = Math.max(Math.min(Math.ceil(($.gameQuery.playground[0].width-tileSetOffset.left)/gameQuery.width), gameQuery.sizex),0); + + for(var i = gameQuery.firstRow; i < gameQuery.lastRow; i++){ + // if old first col < new first col + // deactivate the newly invisible tiles + for(var j = gameQuery.firstColumn; j < firstColumn ; j++) { + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).removeClass("active"); + } + //and activate the newly visible tiles + for(var j = gameQuery.lastColumn; j < lastColumn ; j++) { + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).addClass("active"); + } + + // if old first col > new first col + // deactivate the newly invisible tiles + for(var j = lastColumn; j < gameQuery.lastColumn ; j++) { + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).removeClass("active"); + } + //activate the newly visible tiles + for(var j = firstColumn; j < gameQuery.firstColumn ; j++) { + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).addClass("active"); + } + } + + gameQuery.firstColumn = firstColumn; + gameQuery.lastColumn = lastColumn; + break; + case "top": + //Do we need to activate/desactive the first/last row + var top = parseFloat(transformation.top); + //Get the tileSet offset (relatif to the playground) + var playgroundOffset = $.gameQuery.playground.offset(); + var tileSetOffset = descriptor.parent().offset(); + tileSetOffset = {top: tileSetOffset.top + top - playgroundOffset.top, left: tileSetOffset.left - playgroundOffset.left}; + + //actvates the visible tiles + var firstRow = Math.max(Math.min(Math.floor(-tileSetOffset.top/gameQuery.height), gameQuery.sizey), 0); + var lastRow = Math.max(Math.min(Math.ceil(($.gameQuery.playground[0].height-tileSetOffset.top)/gameQuery.height), gameQuery.sizey), 0); + + + for(var j = gameQuery.firstColumn; j < gameQuery.lastColumn ; j++) { + // if old first row < new first row + // deactivate the newly invisible tiles + for(var i = gameQuery.firstRow; i < firstRow; i++){ + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).removeClass("active"); + } + //and activate the newly visible tiles + for(var i = gameQuery.lastRow; i < lastRow; i++){ + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).addClass("active"); + } + + // if old first row < new first row + // deactivate the newly invisible tiles + for(var i = lastRow; i < gameQuery.lastRow; i++){ + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).removeClass("active"); + } + //and activate the newly visible tiles + for(var i = firstRow; i < gameQuery.firstRow; i++){ + $("#tile_"+descriptor.attr("id")+"_"+i+"_"+j).addClass("active"); + } + } + + gameQuery.firstRow = firstRow; + gameQuery.lastRow = lastRow; + + break; + case "angle": //(in degree) + //TODO + break; + case "factor": + //TODO + break; + } + } + + } else { + var refreshBoundingCircle = $.gameQuery.playground && !$.gameQuery.playground.disableCollision; + + // Update the descriptor + for(property in transformation){ + switch(property){ + case "left": + gameQuery.posx = parseFloat(transformation.left); + if(refreshBoundingCircle){ + gameQuery.boundingCircle.x = gameQuery.posx+gameQuery.width/2; + } + break; + case "top": + gameQuery.posy = parseFloat(transformation.top); + if(refreshBoundingCircle){ + gameQuery.boundingCircle.y = gameQuery.posy+gameQuery.height/2; + } + break; + case "width": + gameQuery.width = parseFloat(transformation.width); + break; + case "height": + gameQuery.height = parseFloat(transformation.height); + break; + case "angle": //(in degree) + gameQuery.angle = parseFloat(transformation.angle); + break; + case "factor": + gameQuery.factor = parseFloat(transformation.factor); + if(refreshBoundingCircle){ + gameQuery.boundingCircle.radius = gameQuery.factor*gameQuery.boundingCircle.originalRadius; + } + break; + } + } + } + }, + + // This is a utility function that returns the radius for a geometry + proj: function (elem, angle) { + switch (elem.geometry){ + case $.gameQuery.GEOMETRY_RECTANGLE : + var b = angle*Math.PI*2/360; + var Rx = Math.abs(Math.cos(b)*elem.width/2*elem.factor)+Math.abs(Math.sin(b)*elem.height/2*elem.factor); + var Ry = Math.abs(Math.cos(b)*elem.height/2*elem.factor)+Math.abs(Math.sin(b)*elem.width/2*elem.factor); + + return {x: Rx, y: Ry}; + } + }, + + // This is a utility function for collision of two object + collide: function(elem1, offset1, elem2, offset2) { + // test real collision (only for two rectangle...) + if((elem1.geometry == $.gameQuery.GEOMETRY_RECTANGLE && elem2.geometry == $.gameQuery.GEOMETRY_RECTANGLE)){ + + var dx = offset2.x + elem2.boundingCircle.x - elem1.boundingCircle.x - offset1.x; + var dy = offset2.y + elem2.boundingCircle.y - elem1.boundingCircle.y - offset1.y; + var a = Math.atan(dy/dx); + + var Dx = Math.abs(Math.cos(a-elem1.angle*Math.PI*2/360)/Math.cos(a)*dx); + var Dy = Math.abs(Math.sin(a-elem1.angle*Math.PI*2/360)/Math.sin(a)*dy); + + var R = $.gameQuery.proj(elem2, elem2.angle-elem1.angle); + + if((elem1.width/2*elem1.factor+R.x <= Dx) || (elem1.height/2*elem1.factor+R.y <= Dy)) { + return false; + } else { + var Dx = Math.abs(Math.cos(a-elem2.angle*Math.PI*2/360)/Math.cos(a)*-dx); + var Dy = Math.abs(Math.sin(a-elem2.angle*Math.PI*2/360)/Math.sin(a)*-dy); + + var R = $.gameQuery.proj(elem1, elem1.angle-elem2.angle); + + if((elem2.width/2*elem2.factor+R.x <= Dx) || (elem2.height/2*elem2.factor+R.y <= Dy)) { + return false; + } else { + return true; + } + } + } else { + return false; + } + } + // This function mute (or unmute) all the sounds. + }, muteSound: function(muted){ + for (var i = $.gameQuery.resourceManager.sounds.length-1 ; i >= 0; i --) { + $.gameQuery.resourceManager.sounds[i].muted(muted); + } + }, playground: function() { + return $.gameQuery.playground + // This function define a callback that will be called upon during the + // loading of the game's resources. The function will recieve as unique + // parameter a number representing the progess percentage. + }, loadCallback: function(callback){ + $.gameQuery.resourceManager.loadCallback = callback; + }}); + + $.fn.extend({ + /** + * Define the div to use for the display the game and initailize it. + * This could be called on any node it doesn't matter. + * The returned node is the playground node. + * This IS a desrtuctive call + **/ + playground: function(options) { + if(this.length == 1){ + if(this[0] == document){ // Old usage check + throw "Old playground usage, use $.playground() to retreive the playground and $('mydiv').playground(options) to set the div!"; + } + options = $.extend({ + height: 320, + width: 480, + refreshRate: 30, + position: "absolute", + keyTracker: false, + disableCollision: false + }, options); + //We save the playground node and set some variable for this node: + $.gameQuery.playground = this; + $.gameQuery.refreshRate = options.refreshRate; + $.gameQuery.playground[0].height = options.height; + $.gameQuery.playground[0].width = options.width; + + // We initialize the apearance of the div + $.gameQuery.playground.css({ + position: options.position, + display: "block", + overflow: "hidden", + height: options.height+"px", + width: options.width+"px" + }) + .append("