TCJSGame State Utilities: Complete Reference Guide
Introduction to State Utilities
TCJSGame provides powerful state utilities through the state
object that allow you to query and monitor game object properties in real-time. These utilities are essential for game logic, collision detection, and dynamic behavior.
📊 State Query Functions
Distance Calculation
// Calculate distance between two components
const distance = state.distance(player, enemy);
// Get distance between component and point
const pointDistance = state.distance(player, {x: 300, y: 200});
// Example: Enemy aggro range
function update() {
const dist = state.distance(player, enemy);
if (dist < 200) { // 200 pixel aggro range
// Enemy detects player and starts chasing
move.pointTo(enemy, player.x, player.y);
move.accelerate(enemy, 0.1, 0, 3);
}
}
// Example: Proximity trigger
const trigger = new Component(50, 50, "transparent", 400, 300, "rect");
function checkProximity() {
if (state.distance(player, trigger) < 75) {
// Player entered trigger area
console.log("Secret area discovered!");
}
}
Rectangle Properties
// Get component's bounding rectangle [x, y, width, height]
const rect = state.rect(player); // Returns [100, 100, 30, 30]
// Example: UI alignment
function alignToComponent(source, target, padding = 10) {
const targetRect = state.rect(target);
source.x = targetRect[0] + targetRect[2] + padding;
source.y = targetRect[1];
}
// Example: Screen bounds checking
function isOnScreen(component) {
const [x, y, width, height] = state.rect(component);
return x >= 0 && x <= display.canvas.width &&
y >= 0 && y <= display.canvas.height;
}
⚙️ Physics State Monitoring
Physics Status
// Check if physics is enabled on a component
const hasPhysics = state.physics(player); // Returns true or false
// Example: Conditional physics application
function applyGravity(component) {
if (!state.physics(component)) {
component.physics = true;
component.gravity = 0.5;
}
}
// Example: Physics-based puzzles
function togglePhysicsPlatform() {
const physicsEnabled = state.physics(movingPlatform);
if (physicsEnabled) {
movingPlatform.physics = false;
movingPlatform.speedX = 0;
movingPlatform.speedY = 0;
}
}
Rotation State
// Check if rotation is enabled
const canRotate = state.changeAngle(player); // Returns boolean
// Get current rotation angle in radians
const angle = state.Angle(player);
// Example: Turret rotation limits
function updateTurret() {
if (state.changeAngle(turret)) {
const currentAngle = state.Angle(turret);
// Limit rotation to 180 degrees
if (currentAngle > Math.PI || currentAngle < -Math.PI) {
turret.angle = 0;
}
}
}
// Example: Convert angle to degrees
function getAngleDegrees(component) {
return state.Angle(component) * (180 / Math.PI);
}
Position Information
// Get position as formatted string "x,y"
const posString = state.pos(player); // Returns "100,200"
// Example: Save game state
function saveGame() {
const saveData = {
playerPosition: state.pos(player),
enemyPosition: state.pos(enemy),
timestamp: Date.now()
};
localStorage.setItem('gameSave', JSON.stringify(saveData));
}
// Example: Load game state
function loadGame() {
const saveData = JSON.parse(localStorage.getItem('gameSave'));
if (saveData) {
const [x, y] = saveData.playerPosition.split(',').map(Number);
move.teleport(player, x, y);
}
}
🎯 Advanced State Combinations
Collision Detection System
// Enhanced collision with state utilities
function advancedCollision(obj1, obj2) {
const dist = state.distance(obj1, obj2);
const rect1 = state.rect(obj1);
const rect2 = state.rect(obj2);
// Fast distance check first
if (dist > 100) return false;
// Precise rectangle collision
return (rect1[0] < rect2[0] + rect2[2] &&
rect1[0] + rect1[2] > rect2[0] &&
rect1[1] < rect2[1] + rect2[3] &&
rect1[1] + rect1[3] > rect2[1]);
}
// Example: Smart enemy AI
function updateEnemyAI() {
const playerRect = state.rect(player);
const enemyRect = state.rect(enemy);
const dist = state.distance(player, enemy);
if (dist < 150) {
// Chase player
move.pointTo(enemy, player.x, player.y);
move.accelerate(enemy, 0.2, 0, 4);
} else if (dist > 400) {
// Return to patrol
patrolBehavior();
}
}
State-Based Animation System
// Animation states based on component properties
const animationStates = {
IDLE: 0,
WALKING: 1,
JUMPING: 2,
FALLING: 3
};
function getAnimationState(character) {
const isGrounded = character.y >= display.canvas.height - character.height;
const isMoving = Math.abs(character.speedX) > 0.1;
if (!isGrounded) {
return character.speedY < 0 ? animationStates.JUMPING : animationStates.FALLING;
} else if (isMoving) {
return animationStates.WALKING;
} else {
return animationStates.IDLE;
}
}
// Example: Apply appropriate animation
function updateCharacterAnimation() {
const animState = getAnimationState(player);
switch(animState) {
case animationStates.IDLE:
player.color = "blue"; // Idle color
break;
case animationStates.WALKING:
player.color = "green"; // Walking color
break;
case animationStates.JUMPING:
player.color = "yellow"; // Jumping color
break;
case animationStates.FALLING:
player.color = "orange"; // Falling color
break;
}
}
🎮 Game Logic Implementation
Health and Damage System
// Health management with state monitoring
class GameCharacter {
constructor(component, maxHealth = 100) {
this.component = component;
this.maxHealth = maxHealth;
this.health = maxHealth;
this.invulnerable = false;
}
takeDamage(amount) {
if (this.invulnerable) return;
this.health -= amount;
this.invulnerable = true;
// Flash effect
const originalColor = this.component.color;
this.component.color = "red";
setTimeout(() => {
this.component.color = originalColor;
this.invulnerable = false;
}, 500);
return this.health <= 0;
}
getHealthPercent() {
return (this.health / this.maxHealth) * 100;
}
}
// Usage
const playerCharacter = new GameCharacter(player, 100);
Score and Progress Tracking
// Game state manager
class GameState {
constructor() {
this.score = 0;
this.level = 1;
this.collectibles = [];
this.startTime = Date.now();
}
addCollectible(component) {
const pos = state.pos(component);
this.collectibles.push({
component: component,
position: pos,
collected: false
});
}
checkCollectionProgress() {
const collected = this.collectibles.filter(c => c.collected).length;
return (collected / this.collectibles.length) * 100;
}
getPlayTime() {
return Math.floor((Date.now() - this.startTime) / 1000);
}
}
// Example usage
const gameState = new GameState();
🔧 Advanced State Patterns
State Machine Implementation
// Finite State Machine for game objects
class StateMachine {
constructor(component) {
this.component = component;
this.states = {};
this.currentState = null;
}
addState(name, onEnter, onUpdate, onExit) {
this.states[name] = { onEnter, onUpdate, onExit };
}
changeState(newState) {
if (this.currentState && this.states[this.currentState].onExit) {
this.states[this.currentState].onExit();
}
this.currentState = newState;
if (this.states[newState].onEnter) {
this.states[newState].onEnter();
}
}
update() {
if (this.currentState && this.states[this.currentState].onUpdate) {
this.states[this.currentState].onUpdate();
}
}
}
// Example: Enemy AI states
const enemyAI = new StateMachine(enemy);
enemyAI.addState('patrol',
() => console.log("Enemy started patrolling"),
() => {
// Patrol behavior using state utilities
const playerDist = state.distance(enemy, player);
if (playerDist < 200) {
enemyAI.changeState('chase');
}
},
() => console.log("Enemy stopped patrolling")
);
enemyAI.addState('chase',
() => console.log("Enemy started chasing"),
() => {
move.pointTo(enemy, player.x, player.y);
move.accelerate(enemy, 0.3, 0, 5);
const playerDist = state.distance(enemy, player);
if (playerDist > 300) {
enemyAI.changeState('patrol');
}
},
() => console.log("Enemy stopped chasing")
);
Event System with State Checks
// Event system based on state conditions
class GameEvent {
constructor(condition, action, oneTime = false) {
this.condition = condition;
this.action = action;
this.oneTime = oneTime;
this.triggered = false;
}
check() {
if (this.oneTime && this.triggered) return;
if (this.condition()) {
this.action();
this.triggered = true;
}
}
}
// Example events
const events = [
// Player reaches specific position
new GameEvent(
() => state.distance(player, {x: 500, y: 300}) < 50,
() => console.log("Player reached the checkpoint!"),
true
),
// Player collects all coins
new GameEvent(
() => coins.every(coin => !coin.visible),
() => console.log("All coins collected! Level complete!"),
true
),
// Continuous event - low health warning
new GameEvent(
() => playerHealth < 30,
() => showLowHealthWarning(),
false
)
];
function checkEvents() {
events.forEach(event => event.check());
}
🎯 Practical Game Examples
Platformer Game State Manager
class PlatformerGame {
constructor() {
this.player = new Component(30, 30, "blue", 100, 100, "rect");
this.player.physics = true;
this.player.gravity = 0.5;
this.enemies = [];
this.platforms = [];
this.coins = [];
this.score = 0;
this.lives = 3;
}
checkGameState() {
// Check if player fell off screen
if (state.rect(this.player)[1] > display.canvas.height) {
this.respawnPlayer();
}
// Check coin collection
this.coins.forEach((coin, index) => {
if (this.player.crashWith(coin)) {
this.score += 10;
coin.hide();
this.coins.splice(index, 1);
}
});
// Check enemy collisions
this.enemies.forEach(enemy => {
if (this.player.crashWith(enemy)) {
this.lives--;
this.respawnPlayer();
}
});
return this.lives > 0;
}
respawnPlayer() {
move.teleport(this.player, 100, 100);
this.player.speedX = 0;
this.player.speedY = 0;
}
getGameStats() {
return {
score: this.score,
lives: this.lives,
coinsRemaining: this.coins.length,
playerPosition: state.pos(this.player),
playTime: Math.floor(display.frameNo / 50) // Approximate seconds
};
}
}
Real-time Debug Information
// Debug overlay showing state information
const debugInfo = new Component(20, 20, "white", 10, 10, "text");
function updateDebugOverlay() {
const info = [
`Position: ${state.pos(player)}`,
`Physics: ${state.physics(player)}`,
`Rotation: ${state.changeAngle(player)}`,
`Angle: ${state.Angle(player).toFixed(2)}rad`,
`Speed: (${player.speedX.toFixed(1)}, ${player.speedY.toFixed(1)})`,
`Frame: ${display.frameNo}`,
`Scene: ${display.scene}`
];
debugInfo.text = info.join('\n');
}
⚡ Performance Optimization
Efficient State Checking
// Optimize frequent state checks
class OptimizedStateChecker {
constructor() {
this.lastCheck = 0;
this.checkInterval = 10; // Check every 10 frames
this.cachedStates = new Map();
}
getCachedDistance(obj1, obj2) {
const key = `distance_${obj1.id}_${obj2.id}`;
if (display.frameNo - this.lastCheck >= this.checkInterval) {
const distance = state.distance(obj1, obj2);
this.cachedStates.set(key, distance);
this.lastCheck = display.frameNo;
return distance;
}
return this.cachedStates.get(key) || 0;
}
}
// Usage
const stateChecker = new OptimizedStateChecker();
function update() {
// Only calculates distance every 10 frames
const dist = stateChecker.getCachedDistance(player, enemy);
if (dist < 100) {
// Chase logic
}
}
📚 Conclusion
TCJSGame's state utilities provide:
- Real-time object monitoring with simple function calls
- Distance calculation for AI and triggers
- Property checking for dynamic behavior
- Position tracking for save systems and debugging
- Physics state management for complex interactions
These utilities work seamlessly with TCJSGame's movement system to create sophisticated game logic with minimal code. By combining state queries with movement functions, you can build complex behaviors, AI systems, and game mechanics efficiently.
The state utilities are particularly powerful for:
- AI behavior trees
- Game progress tracking
- Collision detection systems
- Debug information displays
- Save game functionality
- Dynamic difficulty adjustment
Master these utilities to create responsive, intelligent game objects that react to their environment and player actions!
Top comments (0)