User prompt
Make it so when the game detects the item it the tornado make it so it does not say The item missed the tornado.
User prompt
Make it so it tells you the result of the experiment after each time the item hits the tornado and fly's off the screen.
User prompt
Make it so when you launch it. it goes a bit higher.
User prompt
Can you make it so the tornado does not spin but if the block touches it. it will still act the same
User prompt
Make it so after you shoot the block and it goes off screen it teleports back.
Code edit (1 edits merged)
Please save this source code
User prompt
Tornado Twister Physics Lab
Initial prompt
Make a game that test's tornado physics
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Launchable object class
var LaunchObject = Container.expand(function () {
var self = Container.call(this);
// Properties set on creation: type, mass
self.type = 'box';
self.mass = 1.0;
self.vx = 0;
self.vy = 0;
self.launched = false;
self.inTornado = false;
self.maxHeight = 0;
self.arrow = null;
// Attach correct asset
var assetId = 'object_' + self.type;
var objGfx = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Draw launch arrow (only before launch)
self.showArrow = function (angle, power) {
if (!self.arrow) {
self.arrow = self.addChild(LK.getAsset('arrow', {
anchorX: 0.0,
anchorY: 0.5,
alpha: 0.7
}));
}
self.arrow.rotation = angle;
self.arrow.scaleX = Math.max(0.5, Math.min(power / 30, 2.5));
self.arrow.x = 0;
self.arrow.y = 0;
self.arrow.visible = true;
};
self.hideArrow = function () {
if (self.arrow) self.arrow.visible = false;
};
// Called every tick
self.update = function () {
if (!self.launched) return;
// Gravity
self.vy += 0.18 * self.mass;
// Tornado force
if (tornado) {
var force = tornado.getForce(self);
self.vx += force.fx;
self.vy += force.fy;
// If inside tornado, mark
var dx = self.x - tornado.centerX;
var dy = self.y - tornado.centerY;
var dist = Math.sqrt(dx * dx + dy * dy);
self.inTornado = dist < tornado.radius;
}
// Move
self.x += self.vx;
self.y += self.vy;
// Track max height
if (self.y < self.maxHeight) self.maxHeight = self.y;
// Out of bounds: below screen
if (self.y > 2732 + 200) {
self.destroyed = true;
}
};
return self;
});
// Tornado class: swirling, applies force to objects inside
var Tornado = Container.expand(function () {
var self = Container.call(this);
var tornadoGfx = self.attachAsset('tornado', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Tornado center
self.centerX = 2048 / 2;
self.centerY = 1700;
self.radius = 300;
self.strength = 1.0; // 1.0 = normal, can be changed per round
self.rotationSpeed = 0.04; // radians per tick
// Animate tornado swirl
self.update = function () {
tornadoGfx.rotation += self.rotationSpeed;
};
// Returns force vector {fx, fy} for an object at (x, y) with mass
self.getForce = function (obj) {
var dx = obj.x - self.centerX;
var dy = obj.y - self.centerY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > self.radius) return {
fx: 0,
fy: 0
}; // Outside tornado
// Swirl: perpendicular to radius, magnitude decreases with mass, increases with strength
var angle = Math.atan2(dy, dx) + Math.PI / 2;
var forceMag = self.strength * 2.5 * (1 - dist / self.radius) / (obj.mass || 1);
return {
fx: Math.cos(angle) * forceMag,
fy: Math.sin(angle) * forceMag - 0.12 // Updraft: negative y
};
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222233
});
/****
* Game Code
****/
// Sound for launch
// Launch arrow
// Object types: box, ball, cow, car (different colors/shapes)
// Tornado: swirling ellipse, semi-transparent blue
// --- Global variables ---
var tornado = null;
var currentObject = null;
var launchedObjects = [];
var round = 1;
var roundActive = false;
var dragStart = null;
var dragPower = 0;
var dragAngle = 0;
var resultText = null;
var infoText = null;
var roundText = null;
var nextButton = null;
var objectTypes = [{
type: 'box',
mass: 1.0,
label: 'Box'
}, {
type: 'ball',
mass: 0.7,
label: 'Ball'
}, {
type: 'cow',
mass: 1.8,
label: 'Cow'
}, {
type: 'car',
mass: 2.5,
label: 'Car'
}];
var tornadoStrengths = [1.0, 1.5, 0.7, 2.0, 0.5];
var objectIndex = 0;
// --- UI Elements ---
function showInfo(msg) {
if (!infoText) {
infoText = new Text2(msg, {
size: 70,
fill: "#fff"
});
infoText.anchor.set(0.5, 0);
LK.gui.top.addChild(infoText);
}
infoText.setText(msg);
}
function showResult(msg) {
if (!resultText) {
resultText = new Text2(msg, {
size: 90,
fill: "#fff"
});
resultText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(resultText);
}
resultText.setText(msg);
resultText.visible = true;
}
function hideResult() {
if (resultText) resultText.visible = false;
}
function showRound() {
if (!roundText) {
roundText = new Text2('', {
size: 60,
fill: "#fff"
});
roundText.anchor.set(0.5, 0);
LK.gui.top.addChild(roundText);
}
roundText.setText("Round " + round + " / 5");
}
function showNextButton() {
if (!nextButton) {
nextButton = new Text2('Next', {
size: 80,
fill: 0xFFEB3B
});
nextButton.anchor.set(0.5, 0.5);
nextButton.interactive = true;
nextButton.buttonMode = true;
nextButton.down = function (x, y, obj) {
startRound();
};
LK.gui.bottom.addChild(nextButton);
}
nextButton.visible = true;
}
function hideNextButton() {
if (nextButton) nextButton.visible = false;
}
// --- Game Logic ---
// Place tornado in center lower half
tornado = new Tornado();
tornado.centerX = 2048 / 2;
tornado.centerY = 1700;
tornado.x = tornado.centerX;
tornado.y = tornado.centerY;
game.addChild(tornado);
// Start first round
function startRound() {
hideResult();
hideNextButton();
showRound();
roundActive = true;
// Set tornado strength for this round
tornado.strength = tornadoStrengths[(round - 1) % tornadoStrengths.length];
// Pick object type for this round
objectIndex = (round - 1) % objectTypes.length;
var objType = objectTypes[objectIndex];
// Place object at bottom center
currentObject = new LaunchObject();
currentObject.type = objType.type;
currentObject.mass = objType.mass;
// Attach correct asset
var assetId = 'object_' + currentObject.type;
var objGfx = currentObject.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
currentObject.x = 2048 / 2;
currentObject.y = 2732 - 200;
currentObject.maxHeight = currentObject.y;
currentObject.launched = false;
currentObject.inTornado = false;
currentObject.destroyed = false;
game.addChild(currentObject);
launchedObjects.push(currentObject);
showInfo("Drag and release to launch the " + objType.label + "!\nTornado strength: " + tornado.strength.toFixed(1));
}
// End round, show result, allow next
function endRound() {
roundActive = false;
var obj = currentObject;
var heightGain = Math.max(0, obj.y - obj.maxHeight);
var msg = "Max height above launch: " + Math.round(heightGain) + " px";
if (obj.inTornado) {
msg += "\nThe " + obj.type + " was caught by the tornado!";
} else {
msg += "\nThe " + obj.type + " missed the tornado.";
}
showResult(msg);
if (round < 5) {
showNextButton();
round++;
} else {
showResult("Experiment complete!\nTry again to test more objects.");
LK.setTimeout(function () {
LK.showGameOver();
}, 2200);
}
}
// --- Drag/Launch Controls ---
// Only allow drag on currentObject before launch
game.down = function (x, y, obj) {
if (!roundActive || !currentObject || currentObject.launched) return;
// Only allow drag if touch is near object
var dx = x - currentObject.x;
var dy = y - currentObject.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 120) {
dragStart = {
x: x,
y: y
};
dragPower = 0;
dragAngle = 0;
currentObject.showArrow(0, 0);
}
};
game.move = function (x, y, obj) {
if (!dragStart || !currentObject || currentObject.launched) return;
var dx = x - dragStart.x;
var dy = y - dragStart.y;
dragPower = Math.sqrt(dx * dx + dy * dy);
dragAngle = Math.atan2(dy, dx);
// Limit angle to upward launches only
if (dragAngle > Math.PI / 2) dragAngle = Math.PI / 2;
if (dragAngle < -Math.PI / 2) dragAngle = -Math.PI / 2;
currentObject.showArrow(dragAngle, dragPower);
};
game.up = function (x, y, obj) {
if (!dragStart || !currentObject || currentObject.launched) return;
// Calculate launch velocity (reverse direction: drag back to launch up)
var dx = x - dragStart.x;
var dy = y - dragStart.y;
var power = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
// Only allow upward launches
if (angle > Math.PI / 2) angle = Math.PI / 2;
if (angle < -Math.PI / 2) angle = -Math.PI / 2;
// Convert to velocity (reverse direction)
var v = Math.min(power / 12, 38); // Cap velocity
currentObject.vx = -Math.cos(angle) * v;
currentObject.vy = -Math.sin(angle) * v;
currentObject.launched = true;
currentObject.hideArrow();
dragStart = null;
LK.getSound('launch').play();
};
// --- Main update loop ---
game.update = function () {
// Animate tornado
if (tornado) tornado.update();
// Update all objects
for (var i = launchedObjects.length - 1; i >= 0; i--) {
var obj = launchedObjects[i];
if (obj && obj.update) obj.update();
// End round if launched object is out of bounds
if (obj === currentObject && obj.launched && !obj.destroyed) {
// If object is below screen or has stopped moving
if (obj.y > 2732 + 200 || Math.abs(obj.vx) < 0.2 && Math.abs(obj.vy) < 0.2 && obj.y > tornado.centerY + 400) {
obj.destroyed = true;
LK.setTimeout(endRound, 700);
}
}
// Remove destroyed objects
if (obj.destroyed) {
obj.destroy();
launchedObjects.splice(i, 1);
}
}
};
// --- Start game ---
startRound();
showRound();
showInfo("Drag and release to launch the object into the tornado!"); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,349 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Launchable object class
+var LaunchObject = Container.expand(function () {
+ var self = Container.call(this);
+ // Properties set on creation: type, mass
+ self.type = 'box';
+ self.mass = 1.0;
+ self.vx = 0;
+ self.vy = 0;
+ self.launched = false;
+ self.inTornado = false;
+ self.maxHeight = 0;
+ self.arrow = null;
+ // Attach correct asset
+ var assetId = 'object_' + self.type;
+ var objGfx = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Draw launch arrow (only before launch)
+ self.showArrow = function (angle, power) {
+ if (!self.arrow) {
+ self.arrow = self.addChild(LK.getAsset('arrow', {
+ anchorX: 0.0,
+ anchorY: 0.5,
+ alpha: 0.7
+ }));
+ }
+ self.arrow.rotation = angle;
+ self.arrow.scaleX = Math.max(0.5, Math.min(power / 30, 2.5));
+ self.arrow.x = 0;
+ self.arrow.y = 0;
+ self.arrow.visible = true;
+ };
+ self.hideArrow = function () {
+ if (self.arrow) self.arrow.visible = false;
+ };
+ // Called every tick
+ self.update = function () {
+ if (!self.launched) return;
+ // Gravity
+ self.vy += 0.18 * self.mass;
+ // Tornado force
+ if (tornado) {
+ var force = tornado.getForce(self);
+ self.vx += force.fx;
+ self.vy += force.fy;
+ // If inside tornado, mark
+ var dx = self.x - tornado.centerX;
+ var dy = self.y - tornado.centerY;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ self.inTornado = dist < tornado.radius;
+ }
+ // Move
+ self.x += self.vx;
+ self.y += self.vy;
+ // Track max height
+ if (self.y < self.maxHeight) self.maxHeight = self.y;
+ // Out of bounds: below screen
+ if (self.y > 2732 + 200) {
+ self.destroyed = true;
+ }
+ };
+ return self;
+});
+// Tornado class: swirling, applies force to objects inside
+var Tornado = Container.expand(function () {
+ var self = Container.call(this);
+ var tornadoGfx = self.attachAsset('tornado', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.5
+ });
+ // Tornado center
+ self.centerX = 2048 / 2;
+ self.centerY = 1700;
+ self.radius = 300;
+ self.strength = 1.0; // 1.0 = normal, can be changed per round
+ self.rotationSpeed = 0.04; // radians per tick
+ // Animate tornado swirl
+ self.update = function () {
+ tornadoGfx.rotation += self.rotationSpeed;
+ };
+ // Returns force vector {fx, fy} for an object at (x, y) with mass
+ self.getForce = function (obj) {
+ var dx = obj.x - self.centerX;
+ var dy = obj.y - self.centerY;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > self.radius) return {
+ fx: 0,
+ fy: 0
+ }; // Outside tornado
+ // Swirl: perpendicular to radius, magnitude decreases with mass, increases with strength
+ var angle = Math.atan2(dy, dx) + Math.PI / 2;
+ var forceMag = self.strength * 2.5 * (1 - dist / self.radius) / (obj.mass || 1);
+ return {
+ fx: Math.cos(angle) * forceMag,
+ fy: Math.sin(angle) * forceMag - 0.12 // Updraft: negative y
+ };
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222233
+});
+
+/****
+* Game Code
+****/
+// Sound for launch
+// Launch arrow
+// Object types: box, ball, cow, car (different colors/shapes)
+// Tornado: swirling ellipse, semi-transparent blue
+// --- Global variables ---
+var tornado = null;
+var currentObject = null;
+var launchedObjects = [];
+var round = 1;
+var roundActive = false;
+var dragStart = null;
+var dragPower = 0;
+var dragAngle = 0;
+var resultText = null;
+var infoText = null;
+var roundText = null;
+var nextButton = null;
+var objectTypes = [{
+ type: 'box',
+ mass: 1.0,
+ label: 'Box'
+}, {
+ type: 'ball',
+ mass: 0.7,
+ label: 'Ball'
+}, {
+ type: 'cow',
+ mass: 1.8,
+ label: 'Cow'
+}, {
+ type: 'car',
+ mass: 2.5,
+ label: 'Car'
+}];
+var tornadoStrengths = [1.0, 1.5, 0.7, 2.0, 0.5];
+var objectIndex = 0;
+// --- UI Elements ---
+function showInfo(msg) {
+ if (!infoText) {
+ infoText = new Text2(msg, {
+ size: 70,
+ fill: "#fff"
+ });
+ infoText.anchor.set(0.5, 0);
+ LK.gui.top.addChild(infoText);
+ }
+ infoText.setText(msg);
+}
+function showResult(msg) {
+ if (!resultText) {
+ resultText = new Text2(msg, {
+ size: 90,
+ fill: "#fff"
+ });
+ resultText.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(resultText);
+ }
+ resultText.setText(msg);
+ resultText.visible = true;
+}
+function hideResult() {
+ if (resultText) resultText.visible = false;
+}
+function showRound() {
+ if (!roundText) {
+ roundText = new Text2('', {
+ size: 60,
+ fill: "#fff"
+ });
+ roundText.anchor.set(0.5, 0);
+ LK.gui.top.addChild(roundText);
+ }
+ roundText.setText("Round " + round + " / 5");
+}
+function showNextButton() {
+ if (!nextButton) {
+ nextButton = new Text2('Next', {
+ size: 80,
+ fill: 0xFFEB3B
+ });
+ nextButton.anchor.set(0.5, 0.5);
+ nextButton.interactive = true;
+ nextButton.buttonMode = true;
+ nextButton.down = function (x, y, obj) {
+ startRound();
+ };
+ LK.gui.bottom.addChild(nextButton);
+ }
+ nextButton.visible = true;
+}
+function hideNextButton() {
+ if (nextButton) nextButton.visible = false;
+}
+// --- Game Logic ---
+// Place tornado in center lower half
+tornado = new Tornado();
+tornado.centerX = 2048 / 2;
+tornado.centerY = 1700;
+tornado.x = tornado.centerX;
+tornado.y = tornado.centerY;
+game.addChild(tornado);
+// Start first round
+function startRound() {
+ hideResult();
+ hideNextButton();
+ showRound();
+ roundActive = true;
+ // Set tornado strength for this round
+ tornado.strength = tornadoStrengths[(round - 1) % tornadoStrengths.length];
+ // Pick object type for this round
+ objectIndex = (round - 1) % objectTypes.length;
+ var objType = objectTypes[objectIndex];
+ // Place object at bottom center
+ currentObject = new LaunchObject();
+ currentObject.type = objType.type;
+ currentObject.mass = objType.mass;
+ // Attach correct asset
+ var assetId = 'object_' + currentObject.type;
+ var objGfx = currentObject.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ currentObject.x = 2048 / 2;
+ currentObject.y = 2732 - 200;
+ currentObject.maxHeight = currentObject.y;
+ currentObject.launched = false;
+ currentObject.inTornado = false;
+ currentObject.destroyed = false;
+ game.addChild(currentObject);
+ launchedObjects.push(currentObject);
+ showInfo("Drag and release to launch the " + objType.label + "!\nTornado strength: " + tornado.strength.toFixed(1));
+}
+// End round, show result, allow next
+function endRound() {
+ roundActive = false;
+ var obj = currentObject;
+ var heightGain = Math.max(0, obj.y - obj.maxHeight);
+ var msg = "Max height above launch: " + Math.round(heightGain) + " px";
+ if (obj.inTornado) {
+ msg += "\nThe " + obj.type + " was caught by the tornado!";
+ } else {
+ msg += "\nThe " + obj.type + " missed the tornado.";
+ }
+ showResult(msg);
+ if (round < 5) {
+ showNextButton();
+ round++;
+ } else {
+ showResult("Experiment complete!\nTry again to test more objects.");
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 2200);
+ }
+}
+// --- Drag/Launch Controls ---
+// Only allow drag on currentObject before launch
+game.down = function (x, y, obj) {
+ if (!roundActive || !currentObject || currentObject.launched) return;
+ // Only allow drag if touch is near object
+ var dx = x - currentObject.x;
+ var dy = y - currentObject.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 120) {
+ dragStart = {
+ x: x,
+ y: y
+ };
+ dragPower = 0;
+ dragAngle = 0;
+ currentObject.showArrow(0, 0);
+ }
+};
+game.move = function (x, y, obj) {
+ if (!dragStart || !currentObject || currentObject.launched) return;
+ var dx = x - dragStart.x;
+ var dy = y - dragStart.y;
+ dragPower = Math.sqrt(dx * dx + dy * dy);
+ dragAngle = Math.atan2(dy, dx);
+ // Limit angle to upward launches only
+ if (dragAngle > Math.PI / 2) dragAngle = Math.PI / 2;
+ if (dragAngle < -Math.PI / 2) dragAngle = -Math.PI / 2;
+ currentObject.showArrow(dragAngle, dragPower);
+};
+game.up = function (x, y, obj) {
+ if (!dragStart || !currentObject || currentObject.launched) return;
+ // Calculate launch velocity (reverse direction: drag back to launch up)
+ var dx = x - dragStart.x;
+ var dy = y - dragStart.y;
+ var power = Math.sqrt(dx * dx + dy * dy);
+ var angle = Math.atan2(dy, dx);
+ // Only allow upward launches
+ if (angle > Math.PI / 2) angle = Math.PI / 2;
+ if (angle < -Math.PI / 2) angle = -Math.PI / 2;
+ // Convert to velocity (reverse direction)
+ var v = Math.min(power / 12, 38); // Cap velocity
+ currentObject.vx = -Math.cos(angle) * v;
+ currentObject.vy = -Math.sin(angle) * v;
+ currentObject.launched = true;
+ currentObject.hideArrow();
+ dragStart = null;
+ LK.getSound('launch').play();
+};
+// --- Main update loop ---
+game.update = function () {
+ // Animate tornado
+ if (tornado) tornado.update();
+ // Update all objects
+ for (var i = launchedObjects.length - 1; i >= 0; i--) {
+ var obj = launchedObjects[i];
+ if (obj && obj.update) obj.update();
+ // End round if launched object is out of bounds
+ if (obj === currentObject && obj.launched && !obj.destroyed) {
+ // If object is below screen or has stopped moving
+ if (obj.y > 2732 + 200 || Math.abs(obj.vx) < 0.2 && Math.abs(obj.vy) < 0.2 && obj.y > tornado.centerY + 400) {
+ obj.destroyed = true;
+ LK.setTimeout(endRound, 700);
+ }
+ }
+ // Remove destroyed objects
+ if (obj.destroyed) {
+ obj.destroy();
+ launchedObjects.splice(i, 1);
+ }
+ }
+};
+// --- Start game ---
+startRound();
+showRound();
+showInfo("Drag and release to launch the object into the tornado!");
\ No newline at end of file
Make a car. In-Game asset. 2d. High contrast. No shadows
Make this a tornado. In-Game asset. 2d. High contrast. No shadows
Make a ball. In-Game asset. 2d. High contrast. No shadows
Make a box. In-Game asset. 2d. High contrast. No shadows
Make a cow. In-Game asset. 2d. High contrast. No shadows
Make a arrow. In-Game asset. 2d. High contrast. No shadows