Add terrain object generation and day/night cycle functionality
- Added new tile properties for forestTree, palmTree, and boulder counts in game-map.json and game-map.tmx - Implemented ObjectManager class to handle dynamic object spawning based on tile properties - Added CycleManager class to manage day/night cycle transitions and visual effects - Enhanced player collision detection with both map layers and spawned objects - Updated Game scene to initialize and update new managers - Adjusted player body size for better collision handling
This commit is contained in:
parent
13abba7061
commit
67c207e54e
|
|
@ -307,6 +307,129 @@
|
||||||
"type":"bool",
|
"type":"bool",
|
||||||
"value":true
|
"value":true
|
||||||
}]
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":40
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"palmTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":0
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":7,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":8
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"palmTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"palmTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":15
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"palmTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":10
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"boulder",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":13,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"boulder",
|
||||||
|
"type":"int",
|
||||||
|
"value":8
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":14,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"boulder",
|
||||||
|
"type":"int",
|
||||||
|
"value":20
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"boulder",
|
||||||
|
"type":"int",
|
||||||
|
"value":15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"forestTree",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
}],
|
}],
|
||||||
"tilewidth":100
|
"tilewidth":100
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
|
|
@ -10,6 +10,69 @@
|
||||||
<property name="collides" type="bool" value="true"/>
|
<property name="collides" type="bool" value="true"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="1">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="40"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="2">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="3">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="5"/>
|
||||||
|
<property name="palmTree" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="4">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="0"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="7">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="8"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="8">
|
||||||
|
<properties>
|
||||||
|
<property name="forestTree" type="int" value="15"/>
|
||||||
|
<property name="palmTree" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="10">
|
||||||
|
<properties>
|
||||||
|
<property name="palmTree" type="int" value="15"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="11">
|
||||||
|
<properties>
|
||||||
|
<property name="palmTree" type="int" value="10"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="12">
|
||||||
|
<properties>
|
||||||
|
<property name="boulder" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="13">
|
||||||
|
<properties>
|
||||||
|
<property name="boulder" type="int" value="8"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="14">
|
||||||
|
<properties>
|
||||||
|
<property name="boulder" type="int" value="20"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
|
<tile id="16">
|
||||||
|
<properties>
|
||||||
|
<property name="boulder" type="int" value="15"/>
|
||||||
|
<property name="forestTree" type="int" value="2"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
</tileset>
|
</tileset>
|
||||||
<layer id="1" name="main" width="60" height="40">
|
<layer id="1" name="main" width="60" height="40">
|
||||||
<data encoding="csv">
|
<data encoding="csv">
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,74 @@
|
||||||
|
export class CycleManager {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.currentCycle = 'day';
|
||||||
|
this.cycleTimer = 0;
|
||||||
|
this.cycleDuration = 120; // 3 minutes
|
||||||
|
this.cycles = ['day', 'evening', 'night', 'morning'];
|
||||||
|
|
||||||
|
// Cycle tint values
|
||||||
|
this.tintValues = {
|
||||||
|
'day': 0xffffff, // White (no tint)
|
||||||
|
'evening': 0xffb085, // Orange tint
|
||||||
|
'night': 0x222244, // Dark blue tint
|
||||||
|
'morning': 0xffffaa // Light yellow tint
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cycle tint values
|
||||||
|
this.playerTintValues = {
|
||||||
|
'day': 0xffffff, // White (no tint)
|
||||||
|
'evening': 0xffccaa, // Orange tint
|
||||||
|
'night': 0x8888ff, // Dark blue tint
|
||||||
|
'morning': 0xffffdd // Light yellow tint
|
||||||
|
};
|
||||||
|
|
||||||
|
this.cycleText = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// Create cycle display text in upper right corner
|
||||||
|
this.cycleText = this.scene.add.text(
|
||||||
|
40,
|
||||||
|
40,
|
||||||
|
'Day',
|
||||||
|
{ fontSize: '24px', fill: '#ffffff' }
|
||||||
|
).setShadow(3,3, '#333', 5).setScrollFactor(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(delta) {
|
||||||
|
// Handle cycle timing
|
||||||
|
this.cycleTimer += delta / 1000; // Convert ms to seconds
|
||||||
|
|
||||||
|
if (this.cycleTimer >= this.cycleDuration) {
|
||||||
|
this.nextCycle();
|
||||||
|
this.cycleTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextCycle() {
|
||||||
|
const currentIndex = this.cycles.indexOf(this.currentCycle);
|
||||||
|
const nextIndex = (currentIndex + 1) % this.cycles.length;
|
||||||
|
|
||||||
|
this.currentCycle = this.cycles[nextIndex];
|
||||||
|
|
||||||
|
// Update display text
|
||||||
|
if (this.cycleText) {
|
||||||
|
this.cycleText.setText(this.currentCycle.charAt(0).toUpperCase() + this.currentCycle.slice(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply tint to the terrain layer
|
||||||
|
this.applyTint(this.scene.mainLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyTint(layer) {
|
||||||
|
if (layer && this.tintValues[this.currentCycle]) {
|
||||||
|
layer.setTint(this.tintValues[this.currentCycle]);
|
||||||
|
this.scene.player.setTint(this.playerTintValues[this.currentCycle]);
|
||||||
|
this.scene.objects.setTint(this.playerTintValues[this.currentCycle]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentCycle() {
|
||||||
|
return this.currentCycle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
export class ObjectManager {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.objects = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// Parse main layer for object properties and create objects
|
||||||
|
this.parseLayerForObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
parseLayerForObjects() {
|
||||||
|
const map = this.scene.mainLayer.tilemap;
|
||||||
|
const layerData = this.scene.mainLayer.layer;
|
||||||
|
|
||||||
|
// Iterate through all tiles in the layer
|
||||||
|
for (let y = 0; y < layerData.height; y++) {
|
||||||
|
for (let x = 0; x < layerData.width; x++) {
|
||||||
|
const tile = this.scene.mainLayer.getTileAt(x, y);
|
||||||
|
|
||||||
|
if (tile && tile.properties) {
|
||||||
|
// Check for object-related properties
|
||||||
|
this.createObjectFromTile(tile, x*100+50, y*100+50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createObjectFromTile(tile, x, y) {
|
||||||
|
// Example: Look for a "type" property to determine what object to create
|
||||||
|
const objectType = tile.properties;
|
||||||
|
|
||||||
|
Object.keys(objectType).forEach(key => {
|
||||||
|
const rand = Phaser.Math.Between(1,300);
|
||||||
|
|
||||||
|
if (key === 'palmTree' && rand <= objectType[key]) {
|
||||||
|
const palmTree = this.scene.physics.add.sprite(x, y, 'objects', 0);
|
||||||
|
this.scene.objects.add(palmTree);
|
||||||
|
palmTree.setImmovable(true).setSize(60,100);
|
||||||
|
} else if (key === 'forestTree' && rand <= objectType[key]) {
|
||||||
|
const forestRand = Phaser.Math.Between(1,4);
|
||||||
|
const forestTree = this.scene.physics.add.sprite(x, y, 'objects', forestRand);
|
||||||
|
this.scene.objects.add(forestTree);
|
||||||
|
forestTree.setImmovable(true).setSize(50,100);
|
||||||
|
} else if (key === 'boulder' && rand <= objectType[key]) {
|
||||||
|
const boulder = this.scene.physics.add.sprite(x, y, 'objects', 20);
|
||||||
|
this.scene.objects.add(boulder);
|
||||||
|
boulder.setImmovable(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
createEnemy(x, y, properties) {
|
||||||
|
// Placeholder for enemy creation logic
|
||||||
|
console.log(`Creating enemy at (${x}, ${y}) with properties:`, properties);
|
||||||
|
|
||||||
|
// Example implementation:
|
||||||
|
// const enemy = this.scene.physics.add.sprite(
|
||||||
|
// x * tileWidth + tileWidth / 2,
|
||||||
|
// y * tileHeight + tileHeight / 2,
|
||||||
|
// 'enemy-sprite'
|
||||||
|
// );
|
||||||
|
// this.objects.push(enemy);
|
||||||
|
}
|
||||||
|
|
||||||
|
createCollectible(x, y, properties) {
|
||||||
|
// Placeholder for collectible creation logic
|
||||||
|
console.log(`Creating collectible at (${x}, ${y}) with properties:`, properties);
|
||||||
|
|
||||||
|
// Example implementation:
|
||||||
|
// const collectible = this.scene.physics.add.sprite(
|
||||||
|
// x * tileWidth + tileWidth / 2,
|
||||||
|
// y * tileHeight + tileHeight / 2,
|
||||||
|
// 'collectible-sprite'
|
||||||
|
// );
|
||||||
|
// this.objects.push(collectible);
|
||||||
|
}
|
||||||
|
|
||||||
|
createPlatform(x, y, properties) {
|
||||||
|
// Placeholder for platform creation logic
|
||||||
|
console.log(`Creating platform at (${x}, ${y}) with properties:`, properties);
|
||||||
|
|
||||||
|
// Example implementation:
|
||||||
|
// const platform = this.scene.physics.add.sprite(
|
||||||
|
// x * tileWidth + tileWidth / 2,
|
||||||
|
// y * tileHeight + tileHeight / 2,
|
||||||
|
// 'platform-sprite'
|
||||||
|
// );
|
||||||
|
// platform.setImmovable(true);
|
||||||
|
// this.objects.push(platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(delta) {
|
||||||
|
// Update all created objects
|
||||||
|
this.objects.forEach(object => {
|
||||||
|
if (object.update) {
|
||||||
|
object.update(delta);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ export class Player extends Phaser.GameObjects.Sprite {
|
||||||
scene.add.existing(this);
|
scene.add.existing(this);
|
||||||
scene.physics.world.enable(this);
|
scene.physics.world.enable(this);
|
||||||
this.body.setCollideWorldBounds(true);
|
this.body.setCollideWorldBounds(true);
|
||||||
|
this.body.setSize(50,100);
|
||||||
|
|
||||||
// Set player properties
|
// Set player properties
|
||||||
this.speed = 200;
|
this.speed = 200;
|
||||||
|
|
@ -15,7 +16,6 @@ export class Player extends Phaser.GameObjects.Sprite {
|
||||||
|
|
||||||
// Add input listener for mouse clicks
|
// Add input listener for mouse clicks
|
||||||
scene.input.on('pointerdown', (pointer) => {
|
scene.input.on('pointerdown', (pointer) => {
|
||||||
console.log(pointer);
|
|
||||||
this.moveToPoint(pointer.worldX, pointer.worldY);
|
this.moveToPoint(pointer.worldX, pointer.worldY);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
import { Player } from '../player.js';
|
import { Player } from '../player.js';
|
||||||
|
import { CycleManager } from '../cycle.js';
|
||||||
|
import { ObjectManager } from '../objects.js';
|
||||||
|
|
||||||
export class Game extends Phaser.Scene {
|
export class Game extends Phaser.Scene {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({ key: 'Game' });
|
super({ key: 'Game' });
|
||||||
|
this.cycleManager = null;
|
||||||
|
this.objectManager = null;
|
||||||
|
this.mainLayer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
|
|
@ -12,6 +17,12 @@ export class Game extends Phaser.Scene {
|
||||||
frameHeight: 100
|
frameHeight: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Load objects sprite
|
||||||
|
this.load.spritesheet('objects', 'assets/images/objects.png', {
|
||||||
|
frameWidth: 100,
|
||||||
|
frameHeight: 100
|
||||||
|
});
|
||||||
|
|
||||||
// Load tilemap
|
// Load tilemap
|
||||||
this.load.tilemapTiledJSON('game-map', 'assets/game-map.json');
|
this.load.tilemapTiledJSON('game-map', 'assets/game-map.json');
|
||||||
// Load tileset image
|
// Load tileset image
|
||||||
|
|
@ -26,7 +37,7 @@ export class Game extends Phaser.Scene {
|
||||||
const terrainTileset = map.addTilesetImage('terrain', 'terrain-tileset');
|
const terrainTileset = map.addTilesetImage('terrain', 'terrain-tileset');
|
||||||
|
|
||||||
// Create layer named "main"
|
// Create layer named "main"
|
||||||
const mainLayer = map.createLayer('main', terrainTileset, 0, 0)
|
this.mainLayer = map.createLayer('main', terrainTileset, 0, 0)
|
||||||
.setCollisionByProperty({ collides: true });
|
.setCollisionByProperty({ collides: true });
|
||||||
|
|
||||||
// Set world bounds based on tilemap dimensions
|
// Set world bounds based on tilemap dimensions
|
||||||
|
|
@ -34,21 +45,46 @@ export class Game extends Phaser.Scene {
|
||||||
const worldHeight = map.heightInPixels;
|
const worldHeight = map.heightInPixels;
|
||||||
this.physics.world.setBounds(0, 0, worldWidth, worldHeight);
|
this.physics.world.setBounds(0, 0, worldWidth, worldHeight);
|
||||||
|
|
||||||
|
// Initialize object manager
|
||||||
|
this.objects = this.physics.add.group();
|
||||||
|
this.objectManager = new ObjectManager(this);
|
||||||
|
this.objectManager.init();
|
||||||
|
|
||||||
// Create player at center of screen
|
// Create player at center of screen
|
||||||
this.player = new Player(this, 1600, 3100);
|
this.player = new Player(this, 1600, 3100);
|
||||||
|
|
||||||
// Physics Collisions
|
// Physics Collisions
|
||||||
this.physics.add.collider(this.player, mainLayer);
|
this.physics.add.collider(this.player, this.mainLayer);
|
||||||
|
this.physics.add.collider(this.player, this.objects);
|
||||||
|
|
||||||
// Make camera follow the player
|
// Make camera follow the player
|
||||||
this.cameras.main.startFollow(this.player);
|
this.cameras.main.startFollow(this.player);
|
||||||
this.cameras.main.setBounds(0, 0, worldWidth, worldHeight);
|
this.cameras.main.setBounds(0, 0, worldWidth, worldHeight);
|
||||||
|
|
||||||
|
// Initialize cycle manager
|
||||||
|
this.cycleManager = new CycleManager(this);
|
||||||
|
this.cycleManager.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update(time, delta) {
|
||||||
// Update player
|
// Update player
|
||||||
if (this.player) {
|
if (this.player) {
|
||||||
this.player.update();
|
this.player.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update cycle manager
|
||||||
|
if (this.cycleManager) {
|
||||||
|
this.cycleManager.update(delta);
|
||||||
|
|
||||||
|
// Apply tint to main layer when needed
|
||||||
|
if (this.mainLayer && this.cycleManager.getCurrentCycle() !== 'day') {
|
||||||
|
this.cycleManager.applyTint(this.mainLayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update object manager
|
||||||
|
if (this.objectManager) {
|
||||||
|
this.objectManager.update(delta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue