PK XD: NEONVERSE ULTRA MP
by GoldenRanger231052 lines19.7 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>PK XD: NEONVERSE ULTRA MP</title>
<style>
* {
box-sizing: border-box;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
font-family: Arial, sans-serif;
color: white;
background: #79e8ff;
touch-action: none;
}
#game {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
}
.panel {
background: rgba(17, 19, 46, .82);
border: 1px solid #ffffff55;
border-radius: 15px;
padding: 10px;
backdrop-filter: blur(10px);
}
#topbar {
position: fixed;
top: 10px;
left: 10px;
right: 10px;
display: flex;
justify-content: space-between;
gap: 8px;
pointer-events: none;
}
#brand {
font-size: clamp(13px, 3vw, 22px);
font-weight: bold;
}
#stats {
text-align: right;
color: #ffe66d;
font-weight: bold;
}
#actions {
position: fixed;
top: 82px;
left: 10px;
display: flex;
flex-direction: column;
gap: 7px;
width: 155px;
}
button {
font-size: 12px;
font-weight: bold;
color: white;
background: linear-gradient(135deg, #7857ff, #ff58c8);
border: 1px solid #ffffff77;
border-radius: 11px;
padding: 10px;
cursor: pointer;
}
button:active {
transform: scale(.96);
}
#start {
position: fixed;
inset: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
background: linear-gradient(135deg, #3520a5dd, #05d3e6bb);
}
#card {
width: 440px;
max-width: 100%;
text-align: center;
padding: 25px;
}
#card h1 {
font-size: clamp(28px, 8vw, 45px);
text-shadow: 0 4px #56269d;
margin: 10px 0;
}
#play {
width: 100%;
font-size: 18px;
background: linear-gradient(90deg, #36eaff, #a45cff, #ff5bbb);
}
#notice {
position: fixed;
top: 20%;
left: 50%;
transform: translateX(-50%);
display: none;
text-align: center;
max-width: 85%;
}
#notice.show {
display: block;
}
#hint {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
text-align: center;
font-size: 11px;
width: max-content;
max-width: 90%;
}
#joystick {
position: fixed;
bottom: 25px;
left: 20px;
width: 110px;
height: 110px;
border: 2px solid #ffffff88;
border-radius: 50%;
background: #ffffff22;
display: none;
}
#stick {
position: absolute;
width: 45px;
height: 45px;
left: 31px;
top: 31px;
border-radius: 50%;
background: linear-gradient(135deg, #51f7ff, #a35dff);
border: 2px solid white;
}
#jump {
position: fixed;
right: 22px;
bottom: 35px;
width: 70px;
height: 70px;
border-radius: 50%;
display: none;
text-align: center;
font-size: 19px;
}
@media (pointer: coarse) {
#joystick, #jump {
display: block;
}
#hint {
bottom: 145px;
}
}
@media (max-width: 480px) {
#actions {
top: 85px;
width: 135px;
}
#actions button {
padding: 8px 6px;
font-size: 11px;
}
}
</style>
</head>
<body>
<canvas id="game"></canvas>
<div id="topbar">
<div id="brand" class="panel">
🌈 NEONVERSE ULTRA MP
<div style="font-size:10px">YENİ DÜNYA • 3D MACERA</div>
</div>
<div id="stats" class="panel">
<div id="coins">🪙 000</div>
<div style="font-size:10px;color:white">👥 5 bot</div>
</div>
</div>
<div id="actions">
<button id="petBtn">🐾 Evcil hayvan: Açık</button>
<button id="danceBtn">💃 Dans et!</button>
<button id="portalBtn">🌀 Neon portal</button>
<button id="dayBtn">🌙 Gece / Gündüz</button>
</div>
<div id="notice" class="panel">Neonverse'e hoş geldin!</div>
<div id="hint" class="panel">
WASD: hareket • SPACE: zıpla • Ekranı sürükle: kamera
</div>
<div id="joystick">
<div id="stick"></div>
</div>
<button id="jump">⬆️</button>
<div id="start">
<div id="card" class="panel">
<div style="font-size:50px">🌎✨🛸</div>
<h1>
NEONVERSE<br>
<span style="color:#55f6ff">ULTRA MP</span>
</h1>
<p>
Yepyeni bir dünya seni bekliyor!
Rengârenk mahalleleri keşfet,
neon şehrini dolaş, altınları topla
ve evcil hayvanınla maceraya çık!
</p>
<button id="play">🚀 DÜNYAYA KATIL</button>
<p style="font-size:10px">
Multiplayer demo • Botlar • 3D şehir
</p>
</div>
</div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// ==============================
// OYUN MOTORU
// ==============================
const canvas = document.querySelector("#game");
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true
});
renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5));
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
renderer.outputColorSpace = THREE.SRGBColorSpace;
const scene = new THREE.Scene();
scene.background = new THREE.Color("#7ee7ff");
scene.fog = new THREE.Fog("#9deaff", 100, 240);
const camera = new THREE.PerspectiveCamera(
65,
innerWidth / innerHeight,
0.1,
500
);
scene.add(new THREE.HemisphereLight("#ffffff", "#514080", 2));
const sun = new THREE.DirectionalLight("#fff2d2", 3);
sun.position.set(-35, 70, 35);
sun.castShadow = true;
scene.add(sun);
function material(color, emissive = null) {
return new THREE.MeshStandardMaterial({
color,
roughness: 0.65,
...(emissive ? {
emissive,
emissiveIntensity: 0.6
} : {})
});
}
const box = new THREE.BoxGeometry(1, 1, 1);
const sphere = new THREE.SphereGeometry(1, 18, 14);
const cylinder = new THREE.CylinderGeometry(1, 1, 1, 20);
const ringGeometry = new THREE.TorusGeometry(1, 0.11, 10, 36);
function mesh(geometry, mat, x, y, z, sx=1, sy=1, sz=1) {
const object = new THREE.Mesh(geometry, mat);
object.position.set(x, y, z);
object.scale.set(sx, sy, sz);
object.castShadow = true;
object.receiveShadow = true;
scene.add(object);
return object;
}
function cube(x, y, z, sx, sy, sz, color) {
return mesh(box, material(color), x, y, z, sx, sy, sz);
}
// ==============================
// YENİ DÜNYA
// ==============================
// Büyük çimenlik alan
cube(0, -1.1, 0, 260, 2, 260, "#56d9a2");
// Şehir yolları
for (let z = -90; z <= 90; z += 30) {
cube(0, -0.06, z, 210, 0.12, 7, "#343957");
cube(0, 0.01, z, 210, 0.025, 0.15, "#ffe9a0");
}
for (let x = -90; x <= 90; x += 30) {
cube(x, -0.06, 0, 7, 0.12, 210, "#343957");
cube(x, 0.01, 0, 0.15, 0.025, 210, "#ffe9a0");
}
// Merkez meydanı
cube(0, 0.01, 0, 24, 0.15, 24, "#f8c8f1");
cube(0, 0.1, 0, 16, 0.12, 16, "#d8fbff");
// Neon meydan halkaları
for (const r of [4.3, 6.1]) {
const ring = mesh(
ringGeometry,
material(r === 4.3 ? "#ff4dce" : "#18eaff"),
0, 0.25, 0, r, 0.85, r
);
ring.rotation.x = Math.PI / 2;
}
// ==============================
// RENKLİ EVLER
// ==============================
const houseColors = [
"#ff79c8",
"#6e9bff",
"#ffdc69",
"#62ead0",
"#ba8cff",
"#ff9671"
];
function makeHouse(x, z, i) {
const width = 7 + i % 3;
const height = 5 + (i % 4) * 1.15;
const depth = 7 + i % 2;
cube(
x,
height / 2,
z,
width,
height,
depth,
houseColors[i % houseColors.length]
);
const roof = mesh(
new THREE.ConeGeometry(width * 0.78, 2.6, 4),
material(houseColors[(i + 2) % houseColors.length]),
x,
height + 1.1,
z,
width * 0.9,
1,
depth * 0.9
);
roof.rotation.y = Math.PI / 4;
// Kapı
cube(
x,
height * 0.35,
z + depth / 2 + 0.04,
1.1,
2,
0.1,
"#634a87"
);
// Pencereler
for (const wx of [-width * 0.27, width * 0.27]) {
for (const wy of [height * 0.45, height * 0.72]) {
cube(
x + wx,
wy,
z + depth / 2 + 0.1,
1,
1,
0.12,
"#b7f8ff"
);
}
}
}
let buildingNumber = 0;
for (const x of [-75, -48, -18]) {
for (const z of [-76, -48, 48, 76]) {
makeHouse(x, z, buildingNumber++);
}
}
for (const x of [-75, -48, -18]) {
for (const z of [-76, -48, 48, 76]) {
makeHouse(z, x, buildingNumber++);
}
}
// ==============================
// GELECEK ŞEHRİ
// ==============================
function makeTower(x, z, height, width, color) {
cube(x, height / 2, z, width, height, width * 0.85, color);
cube(
x,
height + 0.35,
z,
width * 0.9,
0.7,
width * 0.76,
"#34385e"
);
for (let y = 2; y < height - 1; y += 2.7) {
cube(
x, y, z + width * 0.43,
width * 0.68, 0.13, 0.08,
"#5df6ff"
);
cube(
x + width * 0.38, y, z,
0.08, 0.13, width * 0.6,
"#ff6edb"
);
}
cube(
x,
height + 1.2,
z,
width * 0.25,
2,
0.25,
"#62faff"
);
const halo = mesh(
ringGeometry,
material("#17cfff"),
x,
height + 2.1,
z,
width * 0.55,
1,
width * 0.55
);
halo.rotation.x = Math.PI / 2;
}
makeTower(42, -55, 30, 9, "#535ca5");
makeTower(63, -23, 42, 10, "#5e4c9e");
makeTower(47, 25, 25, 8, "#3b6e9e");
makeTower(75, 55, 36, 11, "#6a4d99");
makeTower(27, 66, 22, 7, "#4a86a7");
// ==============================
// AĞAÇLAR VE PARK
// ==============================
function makeTree(x, z) {
mesh(
cylinder,
material("#8f5a59"),
x, 1.6, z,
0.55, 3.2, 0.55
);
const colors = ["#61f5b4", "#b0ff67", "#ff99dd"];
const color = colors[Math.floor(Math.random() * colors.length)];
mesh(
sphere,
material(color),
x, 4, z,
2.4, 2.2, 2.4
);
}
[
[-8,-11],
[9,-10],
[-10,10],
[10,11],
[-35,4],
[-42,16],
[-60,10],
[4,43],
[10,51]
].forEach(([x,z]) => makeTree(x,z));
// Banklar
for (const [x,z] of [[-6,-6],[6,-6],[-6,6],[6,6]]) {
cube(x, 0.7, z, 3, 0.3, 0.8, "#ff73c9");
cube(x, 1, z + 0.45, 3, 0.9, 0.25, "#7e4ccc");
}
// ==============================
// UZAY ADASI VE PORTAL
// ==============================
const island = mesh(
new THREE.CylinderGeometry(13, 8, 4, 9),
material("#5542a1"),
0, 12, -103
);
const islandTop = mesh(
new THREE.CylinderGeometry(13, 13, 0.4, 9),
material("#5af5dd"),
0, 14, -103
);
const portalRing = mesh(
ringGeometry,
material("#10caff"),
0, 4, -18,
3.3, 1, 3.3
);
portalRing.rotation.x = Math.PI / 2;
const portalCore = mesh(
new THREE.CircleGeometry(2.85, 40),
new THREE.MeshBasicMaterial({
color: "#8b5dff",
transparent: true,
opacity: 0.7,
side: THREE.DoubleSide
}),
0, 4, -18
);
// Kristaller
for (let i = 0; i < 7; i++) {
const crystal = mesh(
new THREE.ConeGeometry(0.9, 4, 5),
material("#8f4cff"),
-9 + i * 3,
16,
-106 + (i % 2) * 4
);
crystal.rotation.z = i % 2 ? 0.2 : -0.2;
}
// ==============================
// OYUNCU KARAKTERİ
// ==============================
function makeAvatar(color = "#35d8ff", skin = "#ffc79a") {
const group = new THREE.Group();
scene.add(group);
function part(geometry, mat, x, y, z, sx=1, sy=1, sz=1) {
const object = new THREE.Mesh(geometry, mat);
object.position.set(x, y, z);
object.scale.set(sx, sy, sz);
object.castShadow = true;
group.add(object);
return object;
}
part(
box,
material(color),
0, 1.35, 0,
0.85, 1.05, 0.48
);
const head = part(
sphere,
material(skin),
0, 2.25, 0,
0.55, 0.57, 0.52
);
part(
sphere,
material("#3b245e"),
0, 2.57, -0.03,
0.57, 0.32, 0.55
);
const eyes = material("#24213d");
for (const x of [-0.19, 0.19]) {
part(
sphere,
eyes,
x, 2.28, 0.47,
0.055, 0.07, 0.035
);
}
const arms = [];
for (const x of [-0.55, 0.55]) {
const arm = part(
cylinder,
material(color),
x, 1.4, 0,
0.15, 0.7, 0.15
);
arm.rotation.z = x < 0 ? -0.18 : 0.18;
arms.push(arm);
}
const legs = [];
for (const x of [-0.22, 0.22]) {
const leg = part(
cylinder,
material("#f5f6ff"),
x, 0.57, 0,
0.18, 0.65, 0.18
);
legs.push(leg);
part(
box,
material("#ff65bb"),
x, 0.23, 0.1,
0.28, 0.18, 0.42
);
}
group.userData = {head, arms, legs};
return group;
}
const player = makeAvatar();
player.position.set(0, 0, 8);
// ==============================
// EVCİL HAYVAN
// ==============================
const pet = new THREE.Group();
scene.add(pet);
const petBody = mesh(
sphere, material("#ffcc56"),
0, 0.55, 0,
0.58, 0.48, 0.7
);
const petHead = mesh(
sphere, material("#ffdc85"),
0, 0.9, 0.35,
0.48, 0.46, 0.45
);
const petTail = mesh(
sphere, material("#ff8bbf"),
0, 0.64, -0.66,
0.18, 0.18, 0.38
);
pet.add(petBody, petHead, petTail);
pet.position.set(2, 0, 9);
// ==============================
// BOTLAR
// ==============================
const botColors = [
"#ff55ad",
"#ffe066",
"#66ffa9",
"#ac84ff",
"#ff9866"
];
const bots = [];
for (let i = 0; i < 5; i++) {
const bot = makeAvatar(botColors[i]);
bot.position.set(
(Math.random() - 0.5) * 17,
0,
(Math.random() - 0.5) * 17
);
bot.userData.angle = Math.random() * Math.PI * 2;
bot.userData.radius = 6 + Math.random() * 8;
bot.userData.speed = 0.25 + Math.random() * 0.3;
bot.userData.phase = Math.random() * 7;
bots.push(bot);
}
// ==============================
// ALTINLAR
// ==============================
const coins = [];
let collected = 0;
for (let i = 0; i < 35; i++) {
let x = (Math.random() - 0.5) * 150;
let z = (Math.random() - 0.5) * 150;
if (Math.abs(x) < 13 && Math.abs(z) < 13) {
x += 24;
}
const coin = mesh(
new THREE.TorusGeometry(0.48, 0.16, 10, 20),
material("#ffd64f", "#ffc400"),
x, 1.45, z,
0.8, 0.8, 0.8
);
coin.userData.phase = Math.random() * 8;
coin.userData.collected = false;
coins.push(coin);
}
// ==============================
// OYUN KONTROLLERİ
// ==============================
let started = false;
let petFollowing = true;
let dancing = false;
let night = false;
let jumpVelocity = 0;
let grounded = true;
let worldTime = 0;
let yaw = 0;
let pitch = 0.18;
const keys = {};
const notice = document.querySelector("#notice");
function toast(message) {
notice.textContent = message;
notice.classList.add("show");
clearTimeout(toast.timer);
notice.timer = setTimeout(() => {
notice.classList.remove("show");
}, 2200);
}
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
// Oyuna başla
document.querySelector("#play").addEventListener("click", () => {
started = true;
document.querySelector("#start").style.display = "none";
toast("🌈 Neonverse'e hoş geldin!");
});
// Evcil hayvan
document.querySelector("#petBtn").addEventListener("click", () => {
petFollowing = !petFollowing;
document.querySelector("#petBtn").textContent =
petFollowing
? "🐾 Evcil hayvan: Açık"
: "🐾 Evcil hayvan: Bekle";
toast(
petFollowing
? "Minik dostun seni takip ediyor!"
: "Minik dostun bekliyor."
);
});
// Dans
document.querySelector("#danceBtn").addEventListener("click", () => {
dancing = !dancing;
toast(dancing ? "💃 Dans zamanı!" : "🕺 Dans bitti!");
});
// Portal
document.querySelector("#portalBtn").addEventListener("click", () => {
if (Math.abs(player.position.z + 18) < 9) {
player.position.set(0, 0, -100);
toast("🛸 Uzay adasına ışınlandın!");
} else {
player.position.set(0, 0, -12);
toast("🌀 Portal meydanına geldin!");
}
});
// Gece ve gündüz
document.querySelector("#dayBtn").addEventListener("click", () => {
night = !night;
scene.background.set(night ? "#111638" : "#7ee7ff");
scene.fog.color.set(night ? "#24264e" : "#9deaff");
sun.intensity = night ? 0.6 : 3;
toast(night ? "🌙 Neon gecesi!" : "🌞 Gündüz modu!");
});
// Klavye
addEventListener("keydown", event => {
keys[event.code] = true;
if (event.code === "Space") {
event.preventDefault();
if (grounded && started) {
jumpVelocity = 8;
grounded = false;
}
}
});
addEventListener("keyup", event => {
keys[event.code] = false;
});
// Kamera hareketi
let dragging = false;
let lastX = 0;
let lastY = 0;
renderer.domElement.addEventListener("pointerdown", event => {
if (event.pointerType === "mouse" && event.button !== 0) return;
dragging = true;
lastX = event.clientX;
lastY = event.clientY;
renderer.domElement.setPointerCapture?.(event.pointerId);
});
addEventListener("pointerup", () => {
dragging = false;
});
addEventListener("pointermove", event => {
if (!dragging || !started) return;
const dx = event.clientX - lastX;
const dy = event.clientY - lastY;
lastX = event.clientX;
lastY = event.clientY;
yaw -= dx * 0.006;
pitch = clamp(pitch + dy * 0.003, -0.12, 0.85);
});
// Mobil joystick
const joystick = document.querySelector("#joystick");
const stick = document.querySelector("#stick");
let joyX = 0;
let joyY = 0;
let joystickActive = false;
let joystickPointer = null;
function moveJoystick(event) {
const rect = joystick.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const cy = rect.top + rect.height / 2;
joyX = clamp((event.clientX - cx) / 37, -1, 1);
joyY = clamp((event.clientY - cy) / 37, -1, 1);
stick.style.left = (31 + joyX * 26) + "px";
stick.style.top = (31 + joyY * 26) + "px";
}
joystick.addEventListener("pointerdown", event => {
joystickActive = true;
joystickPointer = event.pointerId;
joystick.setPointerCapture(event.pointerId);
moveJoystick(event);
});
joystick.addEventListener("pointermove", event => {
if (
joystickActive &&
event.pointerId === joystickPointer
) {
moveJoystick(event);
}
});
function resetJoystick() {
joystickActive = false;
joyX = 0;
joyY = 0;
stick.style.left = "31px";
stick.style.top = "31px";
}
joystick.addEventListener("pointerup", resetJoystick);
joystick.addEventListener("pointercancel", resetJoystick);
// Mobil zıplama
document.querySelector("#jump").addEventListener("pointerdown", event => {
event.preventDefault();
if (grounded && started) {
jumpVelocity = 8;
grounded = false;
}
});
// Ekran boyutu
addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5));
});
// ==============================
// OYUN DÖNGÜSÜ
// ==============================
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const dt = Math.min(clock.getDelta(), 0.04);
worldTime += dt;
// Portal animasyonu
portalRing.rotation.z += dt * 0.7;
portalCore.material.opacity =
0.45 + Math.sin(worldTime * 3) * 0.18;
// Altın animasyonu
for (const coin of coins) {
if (coin.userData.collected) continue;
coin.rotation.y += dt * 1.7;
coin.position.y =
1.45 +
Math.sin(worldTime * 2 + coin.userData.phase) * 0.25;
const dx = coin.position.x - player.position.x;
const dz = coin.position.z - player.position.z;
if (Math.hypot(dx, dz) < 1.65) {
coin.userData.collected = true;
coin.visible = false;
collected++;
document.querySelector("#coins").textContent =
"🪙 " + String(collected * 10).padStart(3, "0");
if (collected % 5 === 0) {
toast("✨ " + collected * 10 + " jeton kazandın!");
}
}
}
// Kamera yönüne göre hareket
let forward =
(keys.KeyW || keys.ArrowUp ? 1 : 0) -
(keys.KeyS || keys.ArrowDown ? 1 : 0) -
joyY;
let sideways =
(keys.KeyD || keys.ArrowRight ? 1 : 0) -
(keys.KeyA || keys.ArrowLeft ? 1 : 0) +
joyX;
const magnitude = Math.hypot(forward, sideways);
if (magnitude > 1) {
forward /= magnitude;
sideways /= magnitude;
}
const speed =
keys.ShiftLeft || keys.ShiftRight ? 13 : 8;
const dxGame Source: PK XD: NEONVERSE ULTRA MP
Creator: GoldenRanger23
Libraries: three
Complexity: complex (1052 lines, 19.7 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: pk-xd-neonverse-ultra-mp-goldenranger23" to link back to the original. Then publish at arcadelab.ai/publish.