hi I’m new to this community and i have the following problem
i have a Vue JS 3 code about crash game i have issues in the game
the rocket and the curve after 4.5X it goes out the container
i want it to stay inside the container
- the crashed image its gif but its not animating
can someone help me with this issues on vue js 3?!
this is my code:
<template>
<div class="game">
<div class="countdownTimer" v-if="crashed && countdown > 0">
{{ countdown }}
</div>
<div class="gameContainer">
<canvas class="qqq" ref="gameCanvas"></canvas>
<p class="currentMultiplier">{{ currentMultiplier }}x</p>
</div>
<div class="infoContainer">
<div style="display: flex;">
<p class="balance">{{ balanceDisplay }}$</p>
<p class="crashedAt">Multiplier at crash: {{ crashedAt }}</p>
</div>
<div class="betContainer">
<label for="betAmount">Bet Amount:</label>
<input type="number" v-model="betAmount" />
<button @click="placeBet" :disabled="placeBetDisabled">Place Bet</button>
</div>
</div>
<div class="buttonContainer">
<button @click="takeProfits" :disabled="!profitsAvailable || profitsTaken">Take Profits</button>
</div>
<div class="lastCrashesContainer">
<p>Last Crashes:</p>
<div class="lastCrashes">
<img v-for="(crash, index) in lastCrashes" :key="index" :src="crash.imageUrl" :style="{ borderColor: crash.color }" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
countdown: 10,
countdownInterval: null,
gameCanvas: null,
ctx: null,
gameRunning: false,
curvePoints: [1],
gameLoop: null,
balance: 1000,
profitsTaken: false,
crashedAtValue: '',
gameInterval: null,
gameInProgress: false,
crashed: false,
crashedImageUrl: 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif',
isCrashImageVisible: false,
};
},
computed: {
placeBetDisabled() {
return this.gameInProgress || this.profitsTaken;
},
profitsAvailable() {
console.log('Game In Progress:', this.gameInProgress);
console.log('Crashed:', this.crashed);
console.log('Profits Taken:', this.profitsTaken);
return this.gameInProgress && !this.crashed && !this.profitsTaken;
},
profitsAvailable() {
console.log('Crashed:', this.crashed);
console.log('Profits Taken:', this.profitsTaken);
return this.gameInProgress && !this.crashed && !this.profitsTaken;
},
balanceDisplay() {
console.log('Balance:', this.balance);
const balanceAsNumber = parseFloat(this.balance);
if (isNaN(balanceAsNumber)) {
console.error('Invalid balance:', this.balance);
return 'Invalid Balance';
}
return balanceAsNumber.toFixed(2);
},
currentMultiplier() {
const multiplier = (this.curvePoints.length / 100).toFixed(1);
return Math.min(multiplier, 12.0);
},
crashedAt() {
return this.crashed ? this.crashedAtValue : '';
},
lastCrashes() {
return this.curvePoints.map((point) => ({
color: this.profitsTaken ? 'lime' : 'red',
}));
},
profitsAvailable() {
return !this.crashed && !this.profitsTaken;
},
},
mounted() {
this.gameCanvas = this.$refs.gameCanvas;
this.gameCanvas.width = 535; // Adjust width to match gameContainer
this.gameCanvas.height = 462.5; // Adjust height to match gameContainer
this.ctx = this.gameCanvas.getContext('2d');
this.ctx.strokeStyle = '#CE9CFF'; // Set the curve line color to #CE9CFF
this.ctx.lineWidth = 2;
this.preloadImage('https://i.ibb.co/PrfVJbz/hello.png');
this.preloadImage('https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif');
// Start the game loop
this.startGameLoop();
// Start the countdown before the game starts
this.startCountdown();
},
beforeDestroy() {
clearInterval(this.gameLoop);
clearInterval(this.gameInterval);
clearInterval(this.countdownInterval);
},
methods: {
startGameLoop() {
this.gameLoop = setInterval(() => {
this.updateGame();
}, 16);
},
startCountdown() {
this.countdown = 10;
this.countdownInterval = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
} else {
clearInterval(this.countdownInterval);
this.countdownInterval = null;
this.startGame();
}
}, 1000);
},
preloadImage(url) {
const img = new Image();
img.onload = () => {
console.log(`Image loaded: ${url}`);
};
img.onerror = () => {
console.error(`Error loading image: ${url}`);
};
img.src = url;
},
updateCurvePoints() {
const lastPoint = this.curvePoints[this.curvePoints.length - 1];
if (this.currentMultiplier < 12.0) {
const newX = lastPoint.x + 1;
const newY = this.calculateCurveY(newX);
this.curvePoints.push({ x: newX, y: newY });
}
},
updateCurve() {
this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height);
this.ctx.beginPath();
this.curvePoints.forEach((point) => {
this.ctx.lineTo(point.x, point.y);
});
this.ctx.stroke();
// Draw the image based on game state
if (!this.crashed) {
// Draw the rocket if the game is not crashed
const lastPoint = this.curvePoints[this.curvePoints.length - 1];
const rocketImage = new Image();
rocketImage.src = 'https://i.ibb.co/PrfVJbz/hello.png';
const rocketX = lastPoint.x - rocketImage.width / 1.95;
const rocketY = lastPoint.y - rocketImage.height / 1.97;
this.ctx.drawImage(rocketImage, rocketX, rocketY);
} else {
// Draw the crash image if the game is crashed
const crashImage = new Image();
crashImage.src = 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif';
const crashX = this.gameCanvas.width / 2 - crashImage.width / 2;
const crashY = this.gameCanvas.height / 2 - crashImage.height / 2;
// Ensure the crash image is drawn with animation
this.image = document.createElement('img');
this.image.src = crashImage.src;
this.image.style.position = 'absolute';
document.body.appendChild(this.image);
this.image.style.left = crashX + "px";
this.image.style.top = crashY + "px";
}
}
,
// Ensure the multiplier never exceeds 12.0x
currentMultiplier() {
const lastPoint = this.curvePoints[this.curvePoints.length - 1];
const theoreticalMultiplier = (lastPoint.x / 100).toFixed(1);
return Math.min(theoreticalMultiplier, 12.0);
},
getXAtMultiplier(multiplier) {
// Calculate the X value where the multiplier is 12.0x
const x = Math.sqrt(Math.pow(multiplier * this.gameCanvas.height, 2 / 1.75));
return Math.min(x, this.gameCanvas.width); // Ensure x does not exceed canvas width
},
getYAtMultiplier(multiplier) {
// Since Y is directly dependent on X, use the same equation as above
const y = this.gameCanvas.height - Math.pow(this.getXAtMultiplier(multiplier), 1.75) / 100;
return Math.min(y, this.gameCanvas.height); // Ensure y does not exceed canvas height
},
placeBetOrTakeProfits() {
if (this.gameInProgress) {
// If game is in progress, toggle between "Take Profits" and "Place Bet"
if (this.profitsTaken) {
this.takeProfits();
} else {
this.placeBet();
}
} else {
// If game is not in progress, only place the bet
this.placeBet();
}
},
placeBet() {
// Add logic to handle placing a bet
if ((this.gameInProgress || this.countdown > 0) && this.balance >= this.betAmount && this.betAmount > 0) {
// Ensure the bet amount is a positive value and does not exceed the balance
this.balance -= this.betAmount;
// Any additional logic related to placing a bet during the countdown or after a crash
} else {
console.log('Invalid bet amount or insufficient balance');
// Handle invalid bet amount or insufficient balance
}
},
updateCurvePoints() {
const lastPoint = this.curvePoints[this.curvePoints.length - 1];
const newX = lastPoint.x + 1;
const newY = this.gameCanvas.height - Math.pow(newX, 1.75) / 100;
document.querySelector('.currentMultiplier').innerText = (this.curvePoints.length / 100).toFixed(1) + 'x';
this.curvePoints.push({ x: newX, y: newY });
},
updateGame() {
if (this.gameInProgress) {
this.updateCurvePoints();
this.updateCurve();
}
},
crashCurve(betAmount) {
clearInterval(this.gameLoop);
if (this.curvePoints.length >= 2) {
const crashPosition = { x: this.curvePoints[this.curvePoints.length - 2].x, y: this.curvePoints[this.curvePoints.length - 2].y - 10 };
const crashAngle = Math.atan2(
this.curvePoints[this.curvePoints.length - 1].y - this.curvePoints[this.curvePoints.length - 2].y,
this.curvePoints[this.curvePoints.length - 1].x - this.curvePoints[this.curvePoints.length - 2].x
) + Math.PI / 4;
this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height); // Clear the canvas
this.ctx.save();
this.ctx.translate(crashPosition.x, crashPosition.y);
this.ctx.rotate(crashAngle);
const crashImage = new Image();
crashImage.onload = () => {
// Draw the animated crash image with proper size
this.ctx.drawImage(crashImage, -crashImage.width / 2, -crashImage.height / 2, crashImage.width, crashImage.height);
this.ctx.restore();
};
crashImage.onerror = (error) => {
console.error(`Error loading crash image: ${error}`);
};
crashImage.src = 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif';
const crash = document.createElement('p');
crash.innerText = `Crash at ${this.currentMultiplier}x`;
crash.style = 'padding: 0; margin: 0;';
crash.style.color = this.profitsTaken ? 'lime' : 'red';
document.querySelector('.lastCrashes').appendChild(crash);
// Reset the game after a delay
setTimeout(() => {
this.resetGame();
this.startGame();
}, 3000); // Change the delay as needed
} else {
console.error('Invalid curvePoints data for crashing');
}
},
submitBet() {
if (!this.gameInProgress && this.balance > this.betAmount) {
this.balance -= this.betAmount;
this.startGame();
}
},
takeProfits() {
if (this.profitsAvailable) {
console.log('Taking profits...');
this.profitsTaken = true;
// Calculate profit based on the current multiplier
const profit = (this.betAmount * (this.curvePoints.length / 100)).toFixed(2);
// Add the profit to the balance
const newBalance = parseFloat((this.balance + parseFloat(profit)).toFixed(2));
this.balance = newBalance;
} else {
console.log('Profits already taken or game not in progress');
}
} ,
startGame() {
if (this.gameRunning) {
// Only start a new game if the game is not already running
return;
}
this.curvePoints = [{ x: 0, y: this.gameCanvas.height }];
this.resetGame(); // Reset the game-related properties
// ... other setup code ..
this.curvePoints = [{ x: 0, y: this.gameCanvas.height }];
this.gameInProgress = true; // Set gameInProgress to true before starting the game loop
this.profitsTaken = false; // Reset profitsTaken on starting a new game
this.crashed = false; // Reset crashed flag
// Clear previous intervals and reset canvas
clearInterval(this.gameLoop);
this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height);
// Set up an interval to update the game every 16ms
this.startGameLoop();
setTimeout(() => {
this.crashCurve(this.betAmount);
}, this.getRandomCrashTime(1, 12));
},
resetGame() {
this.gameInProgress = false; // Set gameInProgress to false when resetting the game
this.profitsTaken = false; // Reset profitsTaken when the game is reset
// Reset any other necessary game-related properties
},
startGameInterval() {
// Set up an interval to start the game every 10 seconds
this.gameInterval = setInterval(() => {
this.submitBet();
}, 10000);
},
getRandomCrashTime(min, max) {
const randomDecimal = Math.random();
const randomNumber = randomDecimal * (max - min) + min;
return randomNumber * 1000;
},
},
};
</script>
<style scoped>
.qqq{
width: 50rem;
height: 45rem;
}
body {
background-color: #1f1e25;
color: white;
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
.gameContainer {
position: relative;
margin-bottom: 20px;
width: 100%;
height: 100%;
}
.game {
position: absolute;
right: 5rem;
width: 53.5rem;
height: 46.25rem;
background-image: url(../assets/img/back.png);
padding: 0.5rem;
padding-left: 0;
}
.currentMultiplier {
position: absolute;
top: 110px;
left: 70px;
font-size: 50px;
}
.countdownTimer {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 50px;
color: #FFF;
}
.infoContainer {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.balance {
color: lime;
font-weight: bold;
margin-right: 5px;
}
.crashedAt {
margin-right: 5px;
}
.betContainer {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.betContainer label {
margin-right: 5px;
}
#betAmount {
width: 40px;
padding: 5px;
}
.buttonContainer {
margin-bottom: 10px;
width: 400px;
}
button {
display: flex;
width: 17rem;
padding: 0.75rem 1rem;
justify-content: center;
align-items: center;
gap: 0.625rem;
border-radius: 0.5rem;
border: 1px solid rgba(255, 255, 255, 0.20);
background: var(--Style, linear-gradient(180deg, #B352FF 0%, #CE9CFF 100%));
backdrop-filter: blur(4px);
color: #FFF;
text-align: center;
font-family: Satoshi;
font-size: 0.875rem;
font-style: normal;
font-weight: 700;
line-height: 1.25rem; /* 142.857% */
}
.countdownTimer {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 50px;
color: #FFF;
background-color: #333;
padding: 10px 20px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
}
.lastCrashesContainer {
margin-top: 20px;
}
.lastCrashesContainer p {
font-weight: bold;
}
.lastCrashes {
margin-top: 5px;
}
</style>
this is when the rocket and the curve go out the box
I tried To ensure that the curve and the rocket stay within the gameContainer div
and i tried to make the crashed img to be animated but its not working
i tried using chat gpt but with no luck