Hi!
So I have a wix.com website. On one of the pages, I have a HTML game embedded in a HTML embedded box. The game in the iframe collects tokens and at the end of each game (win or lose), the token count is accumilated and displayed within the game.
What I would like to accomplish is to have the tokens collected from every game sent to a custom wix database that collects and compiles tokens as the user plays the game.
For example, a user plays the game and they win, they get 40 tokens. Then, if the player plays again, gets 7 tokens and dies, I'd still like the 7 tokens to be collected. Thus, the user should have 47 tokens displayed on their database.
Not sure of the best logic in this situation and what code to use. I have tried AI and have gotten what seems to be working code, but no success.
I would greatly appreciate some help with logic, code, and any other suggestions in this arena. Either way, I appreciate your time.
website: www.fluxxrpl.com
Current Game Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flappy Flux</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
background-color: #000;
}
canvas {
background-color: transparent;
display: block;
}
#game-container {
position: relative;
}
#startButton, #playAgainButton {
font-size: 24px;
padding: 10px 20px;
background-color: #28a745;
color: white;
border: none;
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
}
#startButton:disabled, #playAgainButton:disabled {
background-color: #ccc;
cursor: not-allowed;
}
position: absolute;
top: 10px;
right: 10px;
color: white;
font-size: 24px;
display: flex;
align-items: center;
}
width: 40px;
height: 40px;
margin-left: 10px;
}
#timer {
position: absolute;
top: 10px;
left: 10px;
font-size: 24px;
color: white;
}
font-size: 32px;
color: white;
position: absolute;
top: 25%;
left: 50%;
transform: translateX(-50%);
display: none;
text-align: center;
}
font-size: 32px;
color: white;
position: absolute;
top: 38%;
left: 50%;
transform: translateX(-50%);
display: none;
}
/* Mute button style */
background-color: transparent;
border: none;
cursor: pointer;
z-index: 100;
margin-right: 10px;
}
width: 30px;
height: 30px;
}
</style>
</head>
<body>
<div id="game-container">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<button id="startButton">Start Game</button>
<button id="playAgainButton" style="display: none;">Play Again?</button>
<div id="tokenCounter">
<button id="muteButton" title="Toggle Mute">
<img id="audioIcon" src="https://static.wixstatic.com/media/15ad31_762054038c3244f19964959556086246~mv2.png" alt="Mute Icon"> <!-- Initial mute icon -->
</button>
<span id="tokenText">0</span>
<img id="tokenImage" src="https://static.wixstatic.com/media/15ad31_6403e757a89745dcb618c8200b818390~mv2.png" alt="Token Image">
</div>
<div id="timer">01:30</div>
<div id="winMessage">You Win +5! <br> You Got <span id="totalTokens">0</span> Tokens</div>
<div id="deathMessage">You Won <span id="tokenAmount">0</span> Tokens!</div>
</div>
<audio id="backgroundMusic" loop>
<source src="https://static.wixstatic.com/mp3/15ad31_ae4856758d35420b87cd43167718c4b3.mp3" type="audio/mp3">
Your browser does not support the audio element.
</audio>
<script>
// Game Constants
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const helicopterImage = new Image();
helicopterImage.src = "https://static.wixstatic.com/media/15ad31_953ba4de831c40d8893561ddac0644a1~mv2.png";
const tokenImage = new Image();
tokenImage.src = "https://static.wixstatic.com/media/15ad31_6403e757a89745dcb618c8200b818390~mv2.png";
// Mute control
let isMuted = false;
const muteButton = document.getElementById("muteButton");
const audioIcon = document.getElementById("audioIcon");
const backgroundMusic = document.getElementById("backgroundMusic");
muteButton.addEventListener("click", toggleMute);
function toggleMute() {
isMuted = !isMuted;
if (isMuted) {
backgroundMusic.pause();
audioIcon.src = "https://static.wixstatic.com/media/15ad31_c2621a38d1c24979a6538b0969b4f196~mv2.png"; // Mute icon
} else {
backgroundMusic.play();
audioIcon.src = "https://static.wixstatic.com/media/15ad31_762054038c3244f19964959556086246~mv2.png"; // Unmute icon
}
}
let helicopterY = 300;
let helicopterX = 100;
const helicopterWidth = 60;
const helicopterHeight = 40;
const gravity = 0.2;
let helicopterVelocity = 0;
let horizontalVelocity = 0;
let isGameOver = false;
let obstacles = [];
let tokens = [];
let stars = [];
// Game Variables
let isSpacePressed = false;
let gameInterval;
let obstacleInterval;
let tokenCount = 0;
let isTimerUp = false;
// Collision tolerance
let collisionTolerance = -9;
// Timer Variables
let timer;
let timeLeft = 90; // 90 seconds (1:30)
let timerInterval;
// UI Elements
const startButton = document.getElementById("startButton");
const playAgainButton = document.getElementById("playAgainButton");
const tokenText = document.getElementById("tokenText");
const tokenAmount = document.getElementById("tokenAmount");
const totalTokens = document.getElementById("totalTokens");
const timerElement = document.getElementById("timer");
const winMessage = document.getElementById("winMessage");
const deathMessage = document.getElementById("deathMessage");
startButton.addEventListener("click", startGame);
playAgainButton.addEventListener("click", resetGame);
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
function createStars() {
stars = [];
for (let i = 0; i < 200; i++) {
stars.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.random() * 2 + 1,
speed: Math.random() * 0.2 + 0.1
});
}
}
function updateStars() {
stars.forEach(star => {
star.x -= star.speed;
if (star.x < 0) {
star.x = canvas.width;
star.y = Math.random() * canvas.height;
}
});
}
function drawStars() {
ctx.fillStyle = "#ffffff";
stars.forEach(star => {
ctx.beginPath();
ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
ctx.fill();
});
}
function startGame() {
startButton.style.display = "none";
playAgainButton.style.display = "none";
winMessage.style.display = "none";
deathMessage.style.display = "none";
resetGameState();
createStars();
clearInterval(gameInterval);
clearInterval(obstacleInterval);
gameInterval = setInterval(updateGame, 1000 / 60);
obstacleInterval = setInterval(generateObstacles, 2500);
if (!isMuted) backgroundMusic.play();
startTimer();
}
function resetGame() {
startButton.style.display = "none";
playAgainButton.style.display = "none";
winMessage.style.display = "none";
deathMessage.style.display = "none";
resetGameState();
createStars();
clearInterval(gameInterval);
clearInterval(obstacleInterval);
gameInterval = setInterval(updateGame, 1000 / 60);
obstacleInterval = setInterval(generateObstacles, 2500);
if (!isMuted) backgroundMusic.play();
resetTimer();
}
function resetGameState() {
isGameOver = false;
helicopterY = canvas.height / 2;
helicopterX = 100;
helicopterVelocity = 0;
horizontalVelocity = 0;
obstacles = [];
tokens = [];
tokenCount = 0;
updateTokenCounter();
timeLeft = 90;
isTimerUp = false;
}
function onKeyDown(event) {
if (event.code === "Space") {
isSpacePressed = true;
}
}
function onKeyUp(event) {
if (event.code === "Space") {
isSpacePressed = false;
}
}
function generateObstacles() {
if (timeLeft <= 5) return;
const gapHeight = 125;
const topObstacleHeight = Math.random() * (canvas.height - gapHeight);
const bottomObstacleHeight = canvas.height - topObstacleHeight - gapHeight;
const obstacleWidth = 45;
obstacles.push({
x: canvas.width,
topHeight: topObstacleHeight,
bottomHeight: bottomObstacleHeight,
width: obstacleWidth
});
const gapTopY = topObstacleHeight;
const gapBottomY = canvas.height - bottomObstacleHeight;
const tokenY = gapTopY + (gapBottomY - gapTopY - 30) / 2;
tokens.push({
x: canvas.width,
y: tokenY,
width: 40,
height: 40
});
}
function updateGame() {
if (isGameOver) return;
updateStars();
if (isSpacePressed) {
helicopterVelocity = -4;
} else {
helicopterVelocity += gravity;
}
helicopterY += helicopterVelocity;
if (isTimerUp && helicopterX < canvas.width) {
horizontalVelocity += 0.05;
}
helicopterX += horizontalVelocity;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawStars();
ctx.drawImage(helicopterImage, helicopterX, helicopterY, helicopterWidth, helicopterHeight);
if (helicopterY <= 0 || helicopterY + helicopterHeight >= canvas.height) {
endGame();
}
ctx.fillStyle = "#228B22";
obstacles.forEach((obstacle, index) => {
obstacle.x -= 3;
ctx.fillRect(obstacle.x, 0, obstacle.width, obstacle.topHeight);
ctx.fillRect(obstacle.x, canvas.height - obstacle.bottomHeight, obstacle.width, obstacle.bottomHeight);
if (helicopterX + helicopterWidth > obstacle.x && helicopterX < obstacle.x + obstacle.width) {
if (helicopterY < obstacle.topHeight + collisionTolerance || helicopterY + helicopterHeight > canvas.height - obstacle.bottomHeight - collisionTolerance) {
endGame();
}
}
if (obstacle.x + obstacle.width < 0) {
obstacles.splice(index, 1);
}
});
tokens.forEach((token, tokenIndex) => {
token.x -= 3;
ctx.drawImage(tokenImage, token.x, token.y, token.width, token.height);
if (helicopterX + helicopterWidth > token.x && helicopterX < token.x + token.width) {
if (helicopterY + helicopterHeight > token.y && helicopterY < token.y + token.height) {
tokens.splice(tokenIndex, 1);
tokenCount += 1;
updateTokenCounter();
}
}
if (token.x + token.width < 0) {
tokens.splice(tokenIndex, 1);
}
});
}
function endGame() {
isGameOver = true;
clearInterval(gameInterval);
clearInterval(obstacleInterval);
playAgainButton.style.display = "block";
backgroundMusic.pause();
backgroundMusic.currentTime = 0;
stopTimer();
if (helicopterX >= canvas.width) {
winGame();
} else {
showDeathMessage();
}
// Send tokens to the main page when the game ends
sendTokensToPage(tokenCount);
}
function showDeathMessage() {
tokenAmount.textContent = tokenCount;
deathMessage.style.display = "block";
}
function updateTokenCounter() {
tokenText.textContent = tokenCount;
}
function startTimer() {
timerInterval = setInterval(function () {
timeLeft--;
let minutes = Math.floor(timeLeft / 60);
let seconds = timeLeft % 60;
if (seconds < 10) {
seconds = "0" + seconds;
}
timerElement.textContent = `${minutes}:${seconds}`;
if (timeLeft <= 10) {
timerElement.style.color = "red";
}
if (timeLeft <= 0) {
clearInterval(timerInterval);
isTimerUp = true;
}
}, 1000);
}
function resetTimer() {
timeLeft = 90;
timerElement.style.color = "white";
timerElement.textContent = "01:30";
startTimer();
}
function stopTimer() {
clearInterval(timerInterval);
}
function winGame() {
tokenCount += 5;
updateTokenCounter();
totalTokens.textContent = tokenCount; // Display total tokens including +5
winMessage.style.display = "block";
}
// Listen for messages from the parent page
window.addEventListener('message', function(event) {
// Check the origin to ensure it's your main page
if (event.origin === 'https://www.fluxxrpl.com') { // Replace with your actual domain
if (event.data.type === 'updateText70') {
const tokens = event.data.tokens;
document.querySelector('#text70').textContent = tokens;
}
}
});
</script>
</body>
</html>
Current front End Code:
// Add this code to your main Wix page (the one containing the iframe)
window.addEventListener('message', function(event) {
// Replace with the actual origin of your game's iframe
if (event.origin === 'https://www.fluxxrpl.com/free-p2e-games-desktop/copy-of-flappy-flux') { // Replace with your game's URL
if (event.data.type === 'gameTokenUpdate') {
const tokens = event.data.tokens;
const targetTextboxId = event.data.targetTextboxId;
// Update the textbox with the token value
const textbox = targetTextboxId.querySelector(targetTextboxId);
if (textbox) {
textbox.textContent = tokens;
} else {
console.error('#text70' + targetTextboxId + ' not found.');
}
}
}
});
Hi, First things first - you can't manipulate the DOM from the Wix frontend/page code. Access to global browser variables such as Window are also restricted. To communicate with your iFrame in Wix you will need to use the Velo APIs such as: https://dev.wix.com/docs/velo/velo-only-apis/$w/html-component/on-message For example:
$w("#myHtmlComponent").onMessage((event) => { if (event.data.type === 'gameTokenUpdate') { const tokens = event.data.tokens; //handle tokens, update database etc. })
Side note - you may want to do a security evaluation as this is all happening on the frontend. Hope that helps, Eitan