User prompt
oyuncunun izlenme başı kazandığı parayı azalt promote ile alınan izleyici sayısını azalt
User prompt
öğretici yazısını ingilizce yaz ve biraz daha büyüt
User prompt
oyunun sol altına öğretici maddeleri ekle
User prompt
oyunda bir süre sonra video yayınlandığında izleyici sayısı artmamaya başlıyor 0'da kalıyor bunu düzelt.
User prompt
Please fix the bug: 'Timeout.tick error: updatePromoteListDisplay is not defined' in or related to this line: 'updatePromoteListDisplay();' Line Number: 2160
User prompt
bir promote yapıldıktan sonra "target: x - y people" yazısındaki "target:" yazısını kaldır
User prompt
Please fix the bug: 'Timeout.tick error: p._promoteListLabel.destroy is not a function' in or related to this line: 'p._promoteListLabel.destroy();' Line Number: 2152
User prompt
Please fix the bug: 'Uncaught TypeError: t.setStageReference is not a function' in or related to this line: 'game.addChild(promoteListLabels[i]);' Line Number: 1041
User prompt
Please fix the bug: 'Uncaught TypeError: promoteListLabels[i].destroy is not a function' in or related to this line: 'promoteListLabels[i].destroy();' Line Number: 888
User prompt
tam istediğim gibi yapmışsın fakat promote your channel panelinde yazılar alt alta yazsın ve ayrı ayrı promotelar yan yana olsun
User prompt
start promote butonun basıldıktan sonra gözükmesini istediğim şey ayrı bir panel değil, promote your channel panelinde aynı video listesinde yaptığımız gibi alt alta şekilde sıralansın ve maksimum 5 farklı promote yapılabilinsin süresi bittikçe yeni promotelar yapılabilinsin. promote yoru channel ekranında conversation rate subs est gibi bilgiler yer almasın kullanıcıya sürpriz olsun.
User prompt
start promote dendikten sonra promote'un bilgileri alt alta yazsın örneğin şu şekilde gözüksün: 1 (harcanacak para) 0.45 (şuana kadar harcanmış güncel para) 678 (şuana kadar reklamın gösterildiği kişi sayısı) 500-1500 (reklam için anlaşılmış gösterilme aralığı) her saat buradaki harcanmış güncel para ve reklamın gösterildiği kişi güncellenecek. Start promote butonuna basıldıktan sonra kullanıcının harcayacağı günlük para gün sayısına bölünecek ve her güne harcanacağı para 24 saate bölünecek ve her saatte kaç izleyici kazanılacağı aralığı hesaplanacak ve saatlik olarak o aralıkta bir güncelleme gerçekleşecek ve gören izleyici sayısına göre bir abonelik artışı olacak. oran mantığını zaten biliyorsun.
User prompt
Please fix the bug: 'Uncaught ReferenceError: moneyInputBg is not defined' in or related to this line: 'moneyInputBg.destroy();' Line Number: 808
User prompt
promote yapma minimum 0 dolar olsun 0 dolar seçiliyse promote yapılamasın ve maksimum güncel paraya kadar arttırabilinsin. eğer kullanıcının güncel parası 0 ise çubuk haraket ettirilemesin ve start promote tuşuna basılamasın. start promote tuşunun içinde yazıyı küçült.
User prompt
estimated reach'i bir aralık olarak göster örneğin 1 dolar harcanıyorsa 500 - 1500 people şeklinde göster kullanıcıya net sayıyı söyleme sürpriz olsun
User prompt
Please fix the bug: 'Uncaught ReferenceError: estSubsTxt is not defined' in or related to this line: 'confirmPromoteBtn.y = estSubsTxt.y + 120;' Line Number: 762
User prompt
promote paneldeki fiyat belirlemeyi ve gün belirlemeyi sağdan sola doğru doğru sürüklenebilen çubuk ile yapalım ve estimated subs gözükmesin kullanıcıya sürpriz olsun sadece estimated reach gözüksün, kullanıcının sürüklenebilir çubukta harcayabileceği para kullanıcının güncel parası olsun, maksimum olabilecek gün 30 gün olsun.
User prompt
promote butonuna basıldığında çıkacak promote butonuna basalım bu ekranda kanalımıza reklam basacağız oyuncu parasını istediği kadar harcayarak kanalını x kadar kullanıcının karşısına çıkarabilecek böylece abone sayacı artacak, her 1 dolar başına 500 ile 1500 arasında rastgele bir değerde kişinin karşısına çıkarılacak kanalı fakat %0.1 ile %2 arasında bir abone olunma oranı olacak. bu promote işlemi anında olmayacak kullanıcı hem harcayacağı parayı seçecek hem de kaç güne yaymak istediğini seçecek ne kadar çok güne bölerse örneğin 10 dolarlık promote yapıldıysa ve 10.000 kişiye gösterilecekse ve bunu 10 güne yaydıysa günlük 1000 kişiye gösterilecek ama %1 ile %1.5 oranına çıkacak geri dönüş oranı yani zamana yayarsa geri dönüş(abonelik) oranı artacak. maksimum 30 güne yayılabilinecek. oyuncu maksimum 5 tane promote yapabilecek onlar da promote panelinin üstünde görünecek. promote ekranında aktif bir promote varken örneğin günde 1000 kişiye gösterilmesi planlanıyorsa günde 24 saat var bu sayı 24 saate rastgele bir şekilde dağıtlacak ve promote ekranında her saat için toplamda şu kadar kişiye bu reklam gösterildi vb. bir veri bulunacak ve saatlik güncellenecek.
User prompt
her 1 izleyici rastgele bir şekilde 0.01 para ile 0.05 para arasında bir miktar para kazandırsın
User prompt
loading barlar her arttığında baştan başlıyor bu bir hata bunu düzelt
User prompt
loading barları daha smooth yap
User prompt
loading barlar hala ani bir şekilde doluyor smooth bir artış olmadı
User prompt
oyundaki loading barların dakika süresine göre artmasını sağla böylece loading barlar daha smooth dolmuş olur.
User prompt
oyun zamanının sadece saat değil dakikayı da aktif hale getir fakat 1x hızda 1 saniyede 1 saat geçmeye 2x hızda 1 saniyede 2 saat geçmeye devam etsin fakat dakika artışı da oranlı olsun birkaç milisaniyede bir artsın oranı sen belirle matematiğim yetmiyor.
User prompt
gerçek hayattaki 1 saniye oyundaki 60 dakikaya eşit olsun.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Energy bar class
var EnergyBar = Container.expand(function () {
var self = Container.call(this);
self.bg = self.attachAsset('energyBarBg', {
anchorX: 0,
anchorY: 0.5
});
self.fill = self.attachAsset('energyBarFill', {
anchorX: 0,
anchorY: 0.5
});
self.fill.x = 0;
self.bg.x = 0;
self.bg.y = 0;
self.fill.y = 0;
self.maxWidth = self.fill.width;
self.set = function (ratio) {
if (ratio < 0) {
ratio = 0;
}
if (ratio > 1) {
ratio = 1;
}
self.fill.width = self.maxWidth * ratio;
};
return self;
});
// Button class for all clickable actions
var GameButton = Container.expand(function () {
var self = Container.call(this);
self.bg = null;
self.label = null;
self.action = null;
self.enabled = true;
self.setButton = function (assetId, labelText, color, width, height) {
self.bg = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.bg.width = width;
self.bg.height = height;
// Modern look: more pronounced rounded corners and soft drop shadow
self.bg.cornerRadius = Math.min(width, height) * 0.28;
self.bg.shadow = {
color: 0x111111,
blur: 36,
offsetX: 0,
offsetY: 16,
alpha: 0.32
};
self.label = new Text2(labelText, {
size: 80,
fill: color,
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 12,
dropShadowDistance: 2
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
};
self.setEnabled = function (val) {
self.enabled = val;
if (self.bg) {
self.bg.alpha = val ? 1 : 0.4;
}
};
self.down = function (x, y, obj) {
if (!self.enabled) {
return;
}
if (typeof self.action === 'function') {
self.action();
}
};
return self;
});
// VideoListItem: displays a video in the list with title, state, and stats
var VideoListItem = Container.expand(function () {
var self = Container.call(this);
self.bg = self.attachAsset('loadingbarempty', {
anchorX: 0,
anchorY: 0.5
});
self.bg.width = 1200;
self.bg.height = 120;
self.bg.alpha = 0.92;
self.titleTxt = new Text2("", {
size: 56,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
self.titleTxt.anchor.set(0, 0.5);
self.titleTxt.x = 40;
self.titleTxt.y = 0;
self.addChild(self.titleTxt);
self.stateTxt = new Text2("", {
size: 44,
fill: "#ff0",
font: "Arial, Helvetica, sans-serif"
});
self.stateTxt.anchor.set(0, 0.5);
self.stateTxt.x = 500;
self.stateTxt.y = 0;
self.addChild(self.stateTxt);
self.statsTxt = new Text2("", {
size: 44,
fill: "#0ff",
font: "Arial, Helvetica, sans-serif"
});
self.statsTxt.anchor.set(0, 0.5);
self.statsTxt.x = 800;
self.statsTxt.y = 0;
self.addChild(self.statsTxt);
self.setVideo = function (videoObj) {
self.titleTxt.setText(videoObj.title || "Untitled");
// State: Recording, Gaining Views, Finished
if (videoObj.hour === 0 && !videoObj.finished) {
self.stateTxt.setText("Just Published");
} else if (!videoObj.finished) {
self.stateTxt.setText("Gaining Views");
} else {
self.stateTxt.setText("Finished");
}
// Stats: views, money, subs
var stats = formatNumber(videoObj.totalViews) + " views";
// Truncate money to 2 decimal digits for display in video list
var moneyDisplay = Math.floor(videoObj.totalMoney * 100) / 100;
stats += " | $" + formatNumber(moneyDisplay);
stats += " | " + formatNumber(videoObj.totalSubs) + " subs";
if (videoObj.trending) {
stats += " | 🔥";
}
self.statsTxt.setText(stats);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Video Categories (must be defined before use in updateTrendingCategory) ---
// --- Trending Category State ---
var videoCategories = ["Vlog", "Challenge", "Reaction", "Tutorial", "Unboxing", "Gaming", "Music", "Comedy", "Q&A", "Other"];
var selectedCategoryIdx = 0;
// Studio background (simple box for now)
// --- Game State Variables ---
// Pick a random trending category at game start
var trendingCategoryIdx = Math.floor(Math.random() * videoCategories.length);
var trendingCategoryDay = 1; // The day this trending category started
function updateTrendingCategory() {
// Pick a new trending category index, different from the current one if possible
var oldIdx = trendingCategoryIdx;
if (videoCategories && videoCategories.length > 1) {
var newIdx;
do {
newIdx = Math.floor(Math.random() * videoCategories.length);
} while (newIdx === oldIdx);
trendingCategoryIdx = newIdx;
} else {
trendingCategoryIdx = 0;
}
trendingCategoryDay = gameDay;
// Set next change day if not already set
if (typeof trendingCategoryNextChangeDay === "undefined") {
trendingCategoryNextChangeDay = trendingCategoryDay + 7 + Math.floor(Math.random() * 24); // 7-30 days
}
}
// If the record video panel is open, update the trending label text if it exists
if (typeof isRecordPanelOpen !== "undefined" && isRecordPanelOpen && typeof categoryBtns !== "undefined") {
for (var i = 0; i < categoryBtns.length; i++) {
if (categoryBtns[i].trendingTxt) {
categoryBtns[i].trendingTxt.setText("Trending");
// Move trending label to the new trending category
if (i === trendingCategoryIdx) {
categoryBtns[i].trendingTxt.visible = true;
} else {
categoryBtns[i].trendingTxt.visible = false;
}
}
// Update button highlight for trending
if (i === trendingCategoryIdx) {
categoryBtns[i].bg.alpha = 0.95;
if (categoryBtns[i].trendingTxt) {
categoryBtns[i].trendingTxt.visible = true;
}
} else {
if (categoryBtns[i].trendingTxt) {
categoryBtns[i].trendingTxt.visible = false;
}
if (i !== selectedCategoryIdx) {
categoryBtns[i].bg.alpha = 0.7;
}
}
}
}
// Video button
// Edit button
// Promote button
// Upgrade button
// Energy bar background
// Energy bar fill
// Subscriber icon
// Money icon
// Sound for making a video
var subscribers = 0;
var viewCount = 0;
var money = 0;
var videoQuality = 1; // upgrades increase this
var editSkill = 1; // upgrades increase this
var promoteSkill = 1; // upgrades increase this
var videoCount = 0;
var upgradeCost = 20;
var upgradeLevel = 1;
// --- Time Mechanics ---
var gameHour = 8; // Start at 8:00
var gameDay = 1;
var isTimePaused = false;
var timeTimer = null;
var timeProcess = null; // {type: 'record'|'edit'|'promote', hoursLeft: int, onFinish: fn}
// --- UI Elements ---
var studioBg = LK.getAsset('studioBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(studioBg);
var computerBg = LK.getAsset('computerbackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(computerBg);
var computerScreen = LK.getAsset('computerscreen', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 485
});
game.addChild(computerScreen);
// Place the videos, record, edit, promote, and statistics buttons equally at the bottom of the computerscreen, no space between them.
var numBtns = 5;
var btnW = computerScreen.width / numBtns;
var btnH = 120;
var csLeft = computerScreen.x - computerScreen.width / 2;
var csBottom = computerScreen.y + computerScreen.height / 2;
// Videos Button
var videosBtn = new GameButton();
videosBtn.setButton('videoBtn', 'Videos', "#fff", btnW, btnH);
videosBtn.x = csLeft + btnW / 2;
videosBtn.y = csBottom - btnH / 2;
videosBtn.action = function () {
// Show video list and background
videoListBg.visible = true;
videoListContainer.visible = true;
// Hide other overlays if needed
statsOverlay.visible = false;
};
game.addChild(videosBtn);
// Helper to hide video list
function hideVideoList() {
videoListBg.visible = false;
videoListContainer.visible = false;
}
// Record Button
var recordVideoBtn = new GameButton();
recordVideoBtn.setButton('promoteBtn', 'Record', "#fff", btnW, btnH);
recordVideoBtn.x = csLeft + btnW * 1.5;
recordVideoBtn.y = csBottom - btnH / 2;
recordVideoBtn.action = function () {
hideVideoList();
if (typeof makeVideoBtn.action === "function") {
makeVideoBtn.action();
}
};
game.addChild(recordVideoBtn);
// Edit Button
var editBtn = new GameButton();
editBtn.setButton('editBtn', 'Edit', "#fff", btnW, btnH);
editBtn.x = csLeft + btnW * 2.5;
editBtn.y = csBottom - btnH / 2;
editBtn.action = function () {
hideVideoList();
// Only allow editing if there is a video in 'recorded' state and not finished, and no process is running
if (timeProcess) return;
if (!window.uploadedVideos) {
// Show message: "You must record a video first!"
var msg = new Text2("You must record a video first!", {
size: 72,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2;
game.addChild(msg);
tween(msg, {
alpha: 0,
y: msg.y - 80
}, {
duration: 1600,
onFinish: function onFinish() {
msg.destroy();
}
});
return;
}
var editIdx = -1;
for (var i = 0; i < window.uploadedVideos.length; i++) {
if (window.uploadedVideos[i].state === "recorded" && !window.uploadedVideos[i].finished) {
editIdx = i;
break;
}
}
if (editIdx === -1) {
// Show message: "You must record a video first!"
var msg = new Text2("You must record a video first!", {
size: 72,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2;
game.addChild(msg);
tween(msg, {
alpha: 0,
y: msg.y - 80
}, {
duration: 1600,
onFinish: function onFinish() {
msg.destroy();
}
});
return;
}
// Open edit panel
var editPanelBg = LK.getAsset('studioBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Use same size as videoListBg, but not equal in pixel size
editPanelBg.width = videoListBg.width + 24;
editPanelBg.height = videoListBg.height - 18;
editPanelBg.x = videoListBg.x + videoListBg.width / 2;
editPanelBg.y = videoListBg.y + videoListBg.height / 2;
editPanelBg.alpha = 0.98;
var editPanelTitle = new Text2("Edit Video", {
size: 90,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
editPanelTitle.anchor.set(0.5, 0.5);
editPanelTitle.x = editPanelBg.x;
editPanelTitle.y = editPanelBg.y - editPanelBg.height / 2 + 120;
// Loading bar background
var loadingBarBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0.5
});
loadingBarBg.width = 800;
loadingBarBg.height = 80;
loadingBarBg.x = editPanelBg.x;
loadingBarBg.y = editPanelBg.y;
// Loading bar fill
var loadingBarFill = LK.getAsset('loadingbarfull', {
anchorX: 0,
anchorY: 0.5
});
loadingBarFill.width = 0;
loadingBarFill.height = 64;
loadingBarFill.x = loadingBarBg.x - loadingBarBg.width / 2 + 4;
loadingBarFill.y = loadingBarBg.y;
// Edit button (just for visual, no action)
var editPanelBtn = new GameButton();
editPanelBtn.setButton('editBtn', 'Edit', "#fff", 400, 120);
editPanelBtn.x = editPanelBg.x;
editPanelBtn.y = loadingBarBg.y + 160;
editPanelBtn.setEnabled(false);
// Close (X) button
var closeEditBtn = new Text2("×", {
size: 120,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
closeEditBtn.anchor.set(0.5, 0.5);
closeEditBtn.x = editPanelBg.x + editPanelBg.width / 2 - 80;
closeEditBtn.y = editPanelBg.y - editPanelBg.height / 2 + 80;
closeEditBtn.interactive = true;
closeEditBtn.buttonMode = true;
closeEditBtn.down = function () {
// Do not allow closing while editing
};
// Add to game
game.addChild(editPanelBg);
game.addChild(editPanelTitle);
game.addChild(loadingBarBg);
game.addChild(loadingBarFill);
game.addChild(editPanelBtn);
game.addChild(closeEditBtn);
// Start editing process for this video
var editVideo = window.uploadedVideos[editIdx];
var totalEdit = editVideo.editHoursLeft || 5;
var hoursLeft = totalEdit;
timeProcess = {
type: 'edit',
hoursLeft: totalEdit,
total: totalEdit,
video: editVideo,
onFinish: function onFinish() {
// Mark video as ready to publish
editVideo.state = "readyToPublish";
editVideo.publishReady = true;
updateVideoLists();
// Remove edit panel
editPanelBg.destroy();
editPanelTitle.destroy();
loadingBarBg.destroy();
loadingBarFill.destroy();
editPanelBtn.destroy();
closeEditBtn.destroy();
}
};
// Animate loading bar fill
var lastEditBarWidth = 0;
var editInterval = LK.setInterval(function () {
if (!timeProcess || timeProcess.type !== 'edit') {
LK.clearInterval(editInterval);
return;
}
var progress = 1 - timeProcess.hoursLeft / (timeProcess.total || 1);
var targetWidth = (loadingBarBg.width - 8) * Math.max(0, Math.min(1, progress));
// Only tween if changed
if (Math.abs(targetWidth - lastEditBarWidth) > 1) {
tween(loadingBarFill, {
width: targetWidth
}, {
duration: 400,
easing: tween.cubicOut
});
lastEditBarWidth = targetWidth;
}
if (timeProcess.hoursLeft <= 0) {
LK.clearInterval(editInterval);
}
}, 100);
};
game.addChild(editBtn);
// Promote Button
var promoteBtn = new GameButton();
promoteBtn.setButton('promoteBtn', 'Promote', "#fff", btnW, btnH);
promoteBtn.x = csLeft + btnW * 3.5;
promoteBtn.y = csBottom - btnH / 2;
promoteBtn.action = function () {
hideVideoList();
// Prevent multiple promote panels
if (game.promotePanelOpen) return;
game.promotePanelOpen = true;
// --- Promote Panel State ---
if (!window.activePromotes) window.activePromotes = [];
var maxPromotes = 5;
// Panel background
var promotePanelBg = LK.getAsset('studioBg', {
anchorX: 0.5,
anchorY: 0.5
});
promotePanelBg.width = videoListBg.width + 24;
promotePanelBg.height = videoListBg.height - 18;
promotePanelBg.x = videoListBg.x + videoListBg.width / 2;
promotePanelBg.y = videoListBg.y + videoListBg.height / 2;
promotePanelBg.alpha = 0.98;
// Title
var promoteTitle = new Text2("Promote Your Channel", {
size: 90,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
promoteTitle.anchor.set(0.5, 0.5);
promoteTitle.x = promotePanelBg.x;
promoteTitle.y = promotePanelBg.y - promotePanelBg.height / 2 + 120;
// --- Active Promotes List (top of panel, in-panel, max 5, no conv/subs est) ---
// Display: Each promote is a vertical stack of 4 labels, and campaigns are side by side horizontally
var promoteListY = promoteTitle.y + 100;
var promoteListLabels = [];
var promoteListMaxW = promotePanelBg.width - 120;
var promoteListStartX = promotePanelBg.x - promoteListMaxW / 2 + 20;
var promoteListStartY = promoteListY + 20;
var promoteListSpacingX = 420; // horizontal space between campaigns
var promoteListSpacingY = 60; // vertical space between lines in a campaign
var promoteLabelFields = [{
key: "amount",
label: "Budget",
prefix: "$"
}, {
key: "spentSoFar",
label: "Spent",
prefix: "$"
}, {
key: "viewsSoFar",
label: "Views",
prefix: "",
isRange: false
}, {
key: "range",
label: "Target",
prefix: "",
isRange: true
}];
// Helper to update the in-panel promote list (max 5, no conv/subs est)
function updatePromoteListDisplay() {
// Remove old
for (var i = 0; i < promoteListLabels.length; i++) {
for (var j = 0; j < promoteListLabels[i].length; j++) {
promoteListLabels[i][j].destroy();
}
}
promoteListLabels = [];
// Show up to 5 active promotes, newest at left
for (var i = 0; i < Math.min(window.activePromotes.length, maxPromotes); i++) {
var p = window.activePromotes[i];
var labels = [];
// Compose each line: Budget, Spent, Views, Target Range
// 1. Budget
var labelTxt1 = promoteLabelFields[0].label + ": $" + p.amount;
var label1 = new Text2(labelTxt1, {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
label1.anchor.set(0.5, 0.5);
label1.x = promoteListStartX + i * promoteListSpacingX + promoteListSpacingX / 2;
label1.y = promoteListStartY + 0 * promoteListSpacingY;
labels.push(label1);
game.addChild(label1);
// 2. Spent so far
var spentDisplay = Math.floor((p.spentSoFar || 0) * 100) / 100;
var labelTxt2 = promoteLabelFields[1].label + ": $" + spentDisplay;
var label2 = new Text2(labelTxt2, {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
label2.anchor.set(0.5, 0.5);
label2.x = promoteListStartX + i * promoteListSpacingX + promoteListSpacingX / 2;
label2.y = promoteListStartY + 1 * promoteListSpacingY;
labels.push(label2);
game.addChild(label2);
// 3. Views so far
var labelTxt3 = promoteLabelFields[2].label + ": " + (p.viewsSoFar || 0);
var label3 = new Text2(labelTxt3, {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
label3.anchor.set(0.5, 0.5);
label3.x = promoteListStartX + i * promoteListSpacingX + promoteListSpacingX / 2;
label3.y = promoteListStartY + 2 * promoteListSpacingY;
labels.push(label3);
game.addChild(label3);
// 4. Target range
var labelTxt4 = p.minViews + "-" + p.maxViews + " people";
var label4 = new Text2(labelTxt4, {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
label4.anchor.set(0.5, 0.5);
label4.x = promoteListStartX + i * promoteListSpacingX + promoteListSpacingX / 2;
label4.y = promoteListStartY + 3 * promoteListSpacingY;
labels.push(label4);
game.addChild(label4);
promoteListLabels.push(labels);
// Store for update
p._promoteListLabel = labels;
}
}
// Initial display
updatePromoteListDisplay();
// --- Money Slider Input ---
// Set promote minimum to 0, and cap to current money, disable if money is 0
var promoteAmount = 0;
var moneySliderBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0.5
});
moneySliderBg.width = 600;
moneySliderBg.height = 100;
moneySliderBg.x = promotePanelBg.x - 250;
moneySliderBg.y = promoteListStartY + maxPromotes * promoteListSpacingY + 80;
moneySliderBg.alpha = 0.92;
// Slider fill
var moneySliderFill = LK.getAsset('loadingbarfull', {
anchorX: 0,
anchorY: 0.5
});
moneySliderFill.height = 80;
moneySliderFill.x = moneySliderBg.x - moneySliderBg.width / 2 + 4;
moneySliderFill.y = moneySliderBg.y;
moneySliderFill.width = 0;
// Slider handle
var moneySliderHandle = LK.getAsset('editBtn', {
anchorX: 0.5,
anchorY: 0.5
});
moneySliderHandle.width = 80;
moneySliderHandle.height = 120;
moneySliderHandle.x = moneySliderBg.x - moneySliderBg.width / 2;
moneySliderHandle.y = moneySliderBg.y;
var moneyInputTxt = new Text2("$" + promoteAmount, {
size: 60,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
moneyInputTxt.anchor.set(0.5, 0.5);
moneyInputTxt.x = moneySliderBg.x;
moneyInputTxt.y = moneySliderBg.y - 70;
// --- Days Slider Input ---
var promoteDays = 1;
var daysSliderBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0.5
});
daysSliderBg.width = 400;
daysSliderBg.height = 100;
daysSliderBg.x = promotePanelBg.x + 350;
daysSliderBg.y = moneySliderBg.y;
daysSliderBg.alpha = 0.92;
var daysSliderFill = LK.getAsset('loadingbarfull', {
anchorX: 0,
anchorY: 0.5
});
daysSliderFill.height = 80;
daysSliderFill.x = daysSliderBg.x - daysSliderBg.width / 2 + 4;
daysSliderFill.y = daysSliderBg.y;
daysSliderFill.width = 0;
var daysSliderHandle = LK.getAsset('editBtn', {
anchorX: 0.5,
anchorY: 0.5
});
daysSliderHandle.width = 80;
daysSliderHandle.height = 120;
daysSliderHandle.x = daysSliderBg.x - daysSliderBg.width / 2;
daysSliderHandle.y = daysSliderBg.y;
var daysInputTxt = new Text2(promoteDays + " day", {
size: 60,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
daysInputTxt.anchor.set(0.5, 0.5);
daysInputTxt.x = daysSliderBg.x;
daysInputTxt.y = daysSliderBg.y - 70;
// --- Slider Drag Logic ---
var draggingMoney = false;
var draggingDays = false;
var lastMoneyX = 0;
var lastDaysX = 0;
function updateMoneySliderFromX(x) {
var min = 0;
var max = Math.max(0, Math.floor(money * 100) / 100);
var left = moneySliderBg.x - moneySliderBg.width / 2;
var right = moneySliderBg.x + moneySliderBg.width / 2;
var clamped = Math.max(left, Math.min(right, x));
var ratio = max === min ? 0 : (clamped - left) / (right - left);
var value = min + (max - min) * ratio;
value = Math.floor(value * 100) / 100;
if (value < min) value = min;
if (value > max) value = max;
promoteAmount = value;
// Update visuals
var fillW = (moneySliderBg.width - 8) * (max === 0 ? 0 : ratio);
moneySliderFill.width = fillW;
moneySliderHandle.x = left + (max === 0 ? 0 : ratio * (right - left));
moneyInputTxt.setText("$" + promoteAmount);
updateEstimates();
}
// Disable slider if money is 0
if (money <= 0) {
moneySliderHandle.interactive = false;
moneySliderHandle.buttonMode = false;
moneySliderBg.interactive = false;
moneySliderBg.buttonMode = false;
promoteAmount = 0;
moneySliderFill.width = 0;
moneySliderHandle.x = moneySliderBg.x - moneySliderBg.width / 2;
moneyInputTxt.setText("$0");
} else {
moneySliderHandle.interactive = true;
moneySliderHandle.buttonMode = true;
moneySliderBg.interactive = true;
moneySliderBg.buttonMode = true;
}
function updateDaysSliderFromX(x) {
var min = 1;
var max = 30;
var left = daysSliderBg.x - daysSliderBg.width / 2;
var right = daysSliderBg.x + daysSliderBg.width / 2;
var clamped = Math.max(left, Math.min(right, x));
var ratio = (clamped - left) / (right - left);
var value = min + (max - min) * ratio;
value = Math.round(value);
if (value < min) value = min;
if (value > max) value = max;
promoteDays = value;
// Update visuals
var fillW = (daysSliderBg.width - 8) * ((promoteDays - min) / (max - min));
daysSliderFill.width = fillW;
daysSliderHandle.x = left + (promoteDays - min) / (max - min) * (right - left);
daysInputTxt.setText(promoteDays + (promoteDays === 1 ? " day" : " days"));
updateEstimates();
}
// Money slider handle drag
moneySliderHandle.interactive = true;
moneySliderHandle.buttonMode = true;
moneySliderHandle.down = function (x, y, obj) {
draggingMoney = true;
lastMoneyX = x;
};
game.move = function (origMove) {
return function (x, y, obj) {
if (draggingMoney) {
updateMoneySliderFromX(x);
}
if (draggingDays) {
updateDaysSliderFromX(x);
}
if (typeof origMove === "function") origMove(x, y, obj);
};
}(game.move);
game.up = function (origUp) {
return function (x, y, obj) {
draggingMoney = false;
draggingDays = false;
if (typeof origUp === "function") origUp(x, y, obj);
};
}(game.up);
// Money slider background tap
moneySliderBg.interactive = true;
moneySliderBg.buttonMode = true;
moneySliderBg.down = function (x, y, obj) {
updateMoneySliderFromX(x);
};
// Days slider handle drag
daysSliderHandle.interactive = true;
daysSliderHandle.buttonMode = true;
daysSliderHandle.down = function (x, y, obj) {
draggingDays = true;
lastDaysX = x;
};
// Days slider background tap
daysSliderBg.interactive = true;
daysSliderBg.buttonMode = true;
daysSliderBg.down = function (x, y, obj) {
updateDaysSliderFromX(x);
};
// --- Estimates Display ---
var estViewsTxt = new Text2("", {
size: 48,
fill: "#0ff",
font: "Arial, Helvetica, sans-serif"
});
estViewsTxt.anchor.set(0.5, 0.5);
estViewsTxt.x = promotePanelBg.x;
estViewsTxt.y = moneySliderBg.y + 120;
// No estimated subs shown!
// --- Confirm Button ---
var confirmPromoteBtn = new GameButton();
confirmPromoteBtn.setButton('promoteBtn', 'Start Promote', "#fff", 480, 130);
confirmPromoteBtn.x = promotePanelBg.x;
confirmPromoteBtn.y = estViewsTxt.y + 120;
confirmPromoteBtn.setEnabled(true);
// Make the label smaller
if (confirmPromoteBtn.label && confirmPromoteBtn.label.style && typeof confirmPromoteBtn.label.style.size !== "undefined") {
confirmPromoteBtn.label.style.size = 44;
confirmPromoteBtn.label.dirty = true;
} else if (confirmPromoteBtn.label && typeof confirmPromoteBtn.label.setStyle === "function") {
confirmPromoteBtn.label.setStyle({
size: 44
});
}
// --- Close Button ---
var closePromoteBtn = new Text2("×", {
size: 120,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
closePromoteBtn.anchor.set(0.5, 0.5);
closePromoteBtn.x = promotePanelBg.x + promotePanelBg.width / 2 - 80;
closePromoteBtn.y = promotePanelBg.y - promotePanelBg.height / 2 + 80;
closePromoteBtn.interactive = true;
closePromoteBtn.buttonMode = true;
closePromoteBtn.down = function () {
promotePanelBg.destroy();
promoteTitle.destroy();
moneySliderBg.destroy();
moneySliderFill.destroy();
moneySliderHandle.destroy();
moneyInputTxt.destroy();
daysSliderBg.destroy();
daysSliderFill.destroy();
daysSliderHandle.destroy();
daysInputTxt.destroy();
estViewsTxt.destroy();
confirmPromoteBtn.destroy();
closePromoteBtn.destroy();
for (var i = 0; i < promoteListLabels.length; i++) {
for (var j = 0; j < promoteListLabels[i].length; j++) {
promoteListLabels[i][j].destroy();
}
}
game.promotePanelOpen = false;
};
// --- Estimate Calculation ---
var estViews = 0,
estSubs = 0,
estConv = 0,
estSubRate = 0;
function updateEstimates() {
// Each $1 = 250-750 views (reduced)
var minViews = Math.floor(promoteAmount * 250);
var maxViews = Math.floor(promoteAmount * 750);
estViews = minViews + Math.floor(Math.random() * (maxViews - minViews + 1));
// Conversion rate: 0.1% - 2% (spread), 1-1.5% if spread over >1 day
if (promoteDays === 1) {
estSubRate = 0.001 + Math.random() * 0.019; // 0.1% - 2%
} else {
estSubRate = 0.01 + Math.random() * 0.005; // 1% - 1.5%
}
estSubs = Math.floor(estViews * estSubRate);
estConv = Math.round(estSubRate * 10000) / 100;
// Show estimated reach as a range, not a single value
estViewsTxt.setText("Estimated Reach: " + formatNumber(minViews) + " - " + formatNumber(maxViews) + " people");
// No estimated subs shown!
// Enable/disable confirm
var canPromote = promoteAmount > 0 && promoteAmount <= money && promoteDays > 0 && promoteDays <= 30 && window.activePromotes.length < maxPromotes && money > 0;
confirmPromoteBtn.setEnabled(canPromote);
// Also disable slider if money is 0
if (money <= 0) {
moneySliderHandle.interactive = false;
moneySliderHandle.buttonMode = false;
moneySliderBg.interactive = false;
moneySliderBg.buttonMode = false;
promoteAmount = 0;
moneySliderFill.width = 0;
moneySliderHandle.x = moneySliderBg.x - moneySliderBg.width / 2;
moneyInputTxt.setText("$0");
} else {
moneySliderHandle.interactive = true;
moneySliderHandle.buttonMode = true;
moneySliderBg.interactive = true;
moneySliderBg.buttonMode = true;
}
}
updateEstimates();
// --- Confirm Promote Action ---
confirmPromoteBtn.action = function () {
if (window.activePromotes.length >= maxPromotes) return;
if (promoteAmount > money) return;
// Deduct money
money -= promoteAmount;
updateStats();
// Schedule promote
var promoteObj = {
amount: promoteAmount,
days: promoteDays,
startDay: gameDay,
targetViews: estViews,
subRate: estSubRate,
estimatedSubs: estSubs,
viewsPerDay: [],
viewsPerHour: [],
subsPerDay: [],
hoursPerDay: [],
hoursLeft: promoteDays * 24,
finished: false,
shownPerHour: [],
subsGained: 0,
lastDay: gameDay + promoteDays - 1,
// New for summary panel
spentSoFar: 0,
viewsSoFar: 0,
summaryPanel: null,
summaryLabels: [],
minViews: Math.floor(promoteAmount * 250),
maxViews: Math.floor(promoteAmount * 750)
};
// Distribute views per day
var perDay = Math.floor(estViews / promoteDays);
var remain = estViews - perDay * promoteDays;
for (var d = 0; d < promoteDays; d++) {
promoteObj.viewsPerDay[d] = perDay + (d < remain ? 1 : 0);
// Distribute per hour randomly
var perHour = Math.floor(promoteObj.viewsPerDay[d] / 24);
var remainHour = promoteObj.viewsPerDay[d] - perHour * 24;
var arr = [];
for (var h = 0; h < 24; h++) arr[h] = perHour;
// Randomly distribute the remainder
for (var h = 0; h < remainHour; h++) {
var idx = Math.floor(Math.random() * 24);
arr[idx]++;
}
promoteObj.viewsPerHour[d] = arr;
promoteObj.shownPerHour[d] = [];
for (var h = 0; h < 24; h++) promoteObj.shownPerHour[d][h] = 0;
}
window.activePromotes.push(promoteObj);
updatePromoteListDisplay();
updateEstimates();
// --- After starting promote, update in-panel promote list and set up per-hour update ---
updatePromoteListDisplay();
updateEstimates();
// Helper to update the label for this promote in the list
promoteObj.updatePromoteListLabel = function () {
if (promoteObj._promoteListLabel && promoteObj._promoteListLabel.length === 4) {
var spentDisplay = Math.floor((promoteObj.spentSoFar || 0) * 100) / 100;
promoteObj._promoteListLabel[0].setText("Budget: $" + promoteObj.amount);
promoteObj._promoteListLabel[1].setText("Spent: $" + spentDisplay);
promoteObj._promoteListLabel[2].setText("Views: " + (promoteObj.viewsSoFar || 0));
promoteObj._promoteListLabel[3].setText(promoteObj.minViews + "-" + promoteObj.maxViews + " people");
}
};
// Show confirmation
var msg = new Text2("Promotion started!", {
size: 72,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
msg.anchor.set(0.5, 0.5);
msg.x = promotePanelBg.x;
msg.y = confirmPromoteBtn.y + 120;
game.addChild(msg);
tween(msg, {
alpha: 0,
y: msg.y - 80
}, {
duration: 1600,
onFinish: function onFinish() {
msg.destroy();
}
});
// Optionally close panel
closePromoteBtn.down();
};
// --- Add to game ---
game.addChild(promotePanelBg);
game.addChild(promoteTitle);
for (var i = 0; i < promoteListLabels.length; i++) {
for (var j = 0; j < promoteListLabels[i].length; j++) {
game.addChild(promoteListLabels[i][j]);
}
}
game.addChild(moneySliderBg);
game.addChild(moneySliderFill);
game.addChild(moneySliderHandle);
game.addChild(moneyInputTxt);
game.addChild(daysSliderBg);
game.addChild(daysSliderFill);
game.addChild(daysSliderHandle);
game.addChild(daysInputTxt);
game.addChild(estViewsTxt);
game.addChild(confirmPromoteBtn);
game.addChild(closePromoteBtn);
};
game.addChild(promoteBtn);
// Statistics Button
var statsBtn = new GameButton();
statsBtn.setButton('editBtn', 'Statistics', "#fff", btnW, btnH);
statsBtn.x = csLeft + btnW * 4.5;
statsBtn.y = csBottom - btnH / 2;
statsBtn.action = function () {
hideVideoList();
updateStatsGraphSingle();
statsOverlay.visible = true;
};
game.addChild(statsBtn);
// --- Time Display ---
// Place time text to the right of the money text
var timeTxt = new Text2('Day 1, 08:00', {
size: 44,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0, 0.5);
// Will be positioned after moneyTxt is created and positioned
// --- Video List UI ---
// Video list background and container (horizontal, each video on a square background, text below, side by side)
var videoListBg = LK.getAsset('loadingbarempty', {
anchorX: 0,
anchorY: 0
});
videoListBg.alpha = 0.96;
videoListBg.visible = false; // Only visible when video list is shown
// Place background to match the computer screen area, but not exceed it
videoListBg.x = computerScreen.x - computerScreen.width / 2 + 16;
videoListBg.y = computerScreen.y - computerScreen.height / 2 + 16 + 150;
videoListBg.width = computerScreen.width - 32;
videoListBg.height = computerScreen.height - 220 - 32 - 150; // leave space for nav bar and reduce 150px from top
game.addChild(videoListBg);
var videoListContainer = new Container();
videoListContainer.x = videoListBg.x + 32; // margin from left inside bg
videoListContainer.y = videoListBg.y + 32; // margin from top inside bg
videoListContainer.visible = false; // Only visible when video list is shown
game.addChild(videoListContainer);
// Helper to update the video list display
function updateVideoLists() {
// Remove all previous children
while (videoListContainer.children.length > 0) {
videoListContainer.children[0].destroy();
}
if (!window.uploadedVideos || window.uploadedVideos.length === 0) {
return;
}
var squareSize = 340;
var spacing = 48;
for (var i = 0; i < window.uploadedVideos.length; i++) {
var video = window.uploadedVideos[i];
// Calculate row and column for 5 per row
var videosPerRow = 5;
var row = Math.floor(i / videosPerRow);
var col = i % videosPerRow;
// Square background
var bg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0.5
});
bg.width = squareSize;
bg.height = squareSize;
bg.x = col * (squareSize + spacing) + squareSize / 2;
bg.y = row * (squareSize + spacing) + squareSize / 2;
bg.alpha = 0.93;
videoListContainer.addChild(bg);
// Video name (title) - top of square
var nameTxt = new Text2(video.title || "Untitled", {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
nameTxt.anchor.set(0.5, 0);
nameTxt.x = bg.x;
nameTxt.y = bg.y - squareSize / 2 + 18;
videoListContainer.addChild(nameTxt);
// Views - below name
var viewsTxt = new Text2(formatNumber(video.totalViews) + " views", {
size: 36,
fill: "#0ff",
font: "Arial, Helvetica, sans-serif"
});
viewsTxt.anchor.set(0.5, 0);
viewsTxt.x = bg.x;
viewsTxt.y = nameTxt.y + nameTxt.height + 6;
videoListContainer.addChild(viewsTxt);
// Money earned - below views
var moneyDisplay = Math.floor(video.totalMoney * 100) / 100;
var moneyTxt = new Text2("$" + formatNumber(moneyDisplay) + " earned", {
size: 36,
fill: 0xFA4B00,
font: "Arial, Helvetica, sans-serif"
});
moneyTxt.anchor.set(0.5, 0);
moneyTxt.x = bg.x;
moneyTxt.y = viewsTxt.y + viewsTxt.height + 2;
videoListContainer.addChild(moneyTxt);
// Subscribers - below money
var subsTxt = new Text2(formatNumber(video.totalSubs) + " subs", {
size: 36,
fill: 0xFFE066,
font: "Arial, Helvetica, sans-serif"
});
subsTxt.anchor.set(0.5, 0);
subsTxt.x = bg.x;
subsTxt.y = moneyTxt.y + moneyTxt.height + 2;
videoListContainer.addChild(subsTxt);
// Status - below subs
// (Removed: status text such as Just Published, Gaining Views, Finished)
// --- Loading Bar (progress for edit/record/publish) ---
var showBar = false;
var barProgress = 0;
var barLabel = "";
if (video.state === "recorded" && !video.finished && typeof video.editHoursLeft === "number" && video.editHoursLeft > 0) {
// Editing in progress or ready to edit
showBar = true;
// If currently editing, show progress
if (timeProcess && timeProcess.type === "edit" && timeProcess.video === video) {
barProgress = 1 - timeProcess.hoursLeft / (timeProcess.total || 1);
barLabel = "Editing...";
} else {
barProgress = 0;
barLabel = "Ready to Edit";
}
} else if (video.state === "readyToPublish" && !video.finished) {
// Ready to publish, no progress bar needed
showBar = true;
barProgress = 1;
barLabel = "Ready to Publish";
} else if (video.state === "published" && !video.finished && typeof video.totalHours === "number" && video.totalHours > 0) {
// Gaining views (publishing progress)
// Fill the bar over 7 days (168 hours)
showBar = true;
var publishTotal = 7 * 24;
barProgress = Math.min(1, video.hour / publishTotal);
barLabel = "Publishing...";
} else if (video.state === "recording" && !video.finished && typeof video.recordHoursLeft === "number" && video.recordHoursLeft > 0) {
// Recording in progress
showBar = true;
if (timeProcess && timeProcess.type === "record" && timeProcess.video === video) {
barProgress = 1 - timeProcess.hoursLeft / (timeProcess.total || 1);
barLabel = "Recording...";
} else {
barProgress = 1 - video.recordHoursLeft / (video.totalRecordHours || 1);
barLabel = "Recording...";
}
}
if (showBar) {
// Bar background
var barBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0
});
barBg.width = squareSize - 40;
barBg.height = 36;
barBg.x = bg.x;
barBg.y = nameTxt.y + nameTxt.height + viewsTxt.height + moneyTxt.height + subsTxt.height + 18;
barBg.alpha = 0.85;
videoListContainer.addChild(barBg);
// Bar fill
var barFill = LK.getAsset('loadingbarfull', {
anchorX: 0,
anchorY: 0
});
// Animate barFill width smoothly using tween, starting from current width
var targetBarWidth = (squareSize - 44) * Math.max(0, Math.min(1, barProgress));
if (typeof video.barLastWidth === "undefined") {
video.barLastWidth = 0;
}
barFill.width = video.barLastWidth;
barFill.height = 28;
barFill.x = barBg.x - barBg.width / 2 + 2;
barFill.y = barBg.y + 4;
barFill.alpha = 0.95;
videoListContainer.addChild(barFill);
tween(barFill, {
width: targetBarWidth
}, {
duration: 400,
easing: tween.cubicOut,
onUpdate: function onUpdate() {
video.barLastWidth = barFill.width;
},
onFinish: function onFinish() {
video.barLastWidth = targetBarWidth;
}
});
// Bar label
var barTxt = new Text2(barLabel, {
size: 28,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
barTxt.anchor.set(0.5, 0.5);
barTxt.x = barBg.x;
barTxt.y = barBg.y + barBg.height / 2;
videoListContainer.addChild(barTxt);
}
// Optionally, trending badge (top of square, above name)
if (video.trending) {
var trendingTxt = new Text2("Trending", {
size: 32,
fill: "#ff0",
font: "Arial, Helvetica, sans-serif"
});
trendingTxt.anchor.set(0.5, 1);
trendingTxt.x = bg.x;
trendingTxt.y = bg.y - squareSize / 2 + 8;
videoListContainer.addChild(trendingTxt);
}
// --- Edit and Publish Buttons ---
// Only show publish button if video is ready to publish and not finished
if (video.state === "readyToPublish" && video.publishReady && !video.finished) {
var publishBtn = new GameButton();
publishBtn.setButton('videoBtn', '', "#fff", 180, 80);
// Make the publish text smaller
var publishLabel = new Text2('Publish', {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
publishLabel.anchor.set(0.5, 0.5);
publishLabel.x = 0;
publishLabel.y = 0;
publishBtn.addChild(publishLabel);
// Place the publish button at the bottom center of the video's background
publishBtn.x = bg.x;
publishBtn.y = bg.y + bg.height / 2 - publishBtn.bg.height / 2 - 10;
publishBtn.action = function (vidIdx) {
return function () {
// Publish the video
var vid = window.uploadedVideos[vidIdx];
vid.state = "published";
vid.hour = 0; // Start accruing views
vid.publishReady = false;
updateVideoLists();
};
}(i);
videoListContainer.addChild(publishBtn);
}
// Only show publish button if video is ready to publish and not finished
if (video.state === "readyToPublish" && video.publishReady && !video.finished) {
var publishBtn = new GameButton();
publishBtn.setButton('videoBtn', '', "#fff", 180, 80);
// Make the publish text smaller
var publishLabel = new Text2('Publish', {
size: 44,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
publishLabel.anchor.set(0.5, 0.5);
publishLabel.x = 0;
publishLabel.y = 0;
publishBtn.addChild(publishLabel);
// Place the publish button at the bottom center of the video's background
publishBtn.x = bg.x;
publishBtn.y = bg.y + bg.height / 2 - publishBtn.bg.height / 2 - 10;
publishBtn.action = function (vidIdx) {
return function () {
// Publish the video
var vid = window.uploadedVideos[vidIdx];
vid.state = "published";
vid.hour = 0; // Start accruing views
vid.publishReady = false;
updateVideoLists();
};
}(i);
videoListContainer.addChild(publishBtn);
}
}
}
// --- Pause/Resume/Double Speed Buttons ---
// Track time speed: 0 = paused, 1 = normal, 2 = double
var timeSpeed = 1;
// Pause button
var pauseBtn = new GameButton();
pauseBtn.setButton('pauseicon', '', "#fff", 54, 54);
pauseBtn.action = function () {
if (timeSpeed !== 0) {
timeSpeed = 0;
isTimePaused = true;
}
updateTimeControlButtons();
};
// Resume button
var resumeBtn = new GameButton();
resumeBtn.setButton('resumeicon', '', "#fff", 54, 54);
resumeBtn.action = function () {
if (timeSpeed !== 1) {
timeSpeed = 1;
isTimePaused = false;
}
updateTimeControlButtons();
};
// Double speed button
var doubleSpeedBtn = new GameButton();
// Double the size: 54*2 = 108
doubleSpeedBtn.setButton('doublespeedicon', '', "#fff", 108, 108);
doubleSpeedBtn.action = function () {
if (timeSpeed !== 2) {
timeSpeed = 2;
isTimePaused = false;
}
updateTimeControlButtons();
};
// Helper to update button enabled/disabled state and highlight
function updateTimeControlButtons() {
// Highlight the selected speed, dim others
pauseBtn.setEnabled(timeSpeed !== 0 ? true : false);
resumeBtn.setEnabled(timeSpeed !== 1 ? true : false);
doubleSpeedBtn.setEnabled(timeSpeed !== 2 ? true : false);
// Optionally, visually highlight the active button
pauseBtn.bg.alpha = timeSpeed === 0 ? 1 : 0.6;
resumeBtn.bg.alpha = timeSpeed === 1 ? 1 : 0.6;
doubleSpeedBtn.bg.alpha = timeSpeed === 2 ? 1 : 0.6;
}
// Initial highlight
updateTimeControlButtons();
// --- Position time text and pause/resume/double speed buttons to the right of the money text ---
// This must be done after moneyTxt is created and positioned, so move this block after moneyTxt and icons are created and layoutCountersRow() is called.
// --- Counter Row Display (subscribers, viewers, money) ---
// Helper to position counters/icons in a row, matching the viewer counter/icon position
function layoutCountersRow() {
var counterY = 160;
var centerX = 2048 / 2;
var iconSpacing = 420;
// Subscribers (left, further left)
subIcon.x = centerX - iconSpacing * 1.7;
subIcon.y = counterY;
subTxt.x = subIcon.x + 70;
subTxt.y = subIcon.y;
// Viewers (shifted further left from center)
viewIcon.x = centerX - iconSpacing * 0.9;
viewIcon.y = counterY;
viewTxt.x = viewIcon.x + 70;
viewTxt.y = viewIcon.y;
// Money (move further left)
moneyIcon.x = centerX + iconSpacing * 0.1;
moneyIcon.y = counterY;
moneyTxt.x = moneyIcon.x + 70;
moneyTxt.y = moneyIcon.y;
}
// Create icons and text objects
var subIcon = LK.getAsset('subIcon', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(subIcon);
var subTxt = new Text2('0', {
size: 64,
fill: 0xFFFFFF
});
subTxt.anchor.set(0, 0.5);
game.addChild(subTxt);
var viewIcon = LK.getAsset('viewersicon', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(viewIcon);
var viewTxt = new Text2('0', {
size: 64,
fill: 0x00e0ff
});
viewTxt.anchor.set(0, 0.5);
game.addChild(viewTxt);
var moneyIcon = LK.getAsset('moneyIcon', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(moneyIcon);
var moneyTxt = new Text2('0', {
size: 64,
fill: 0xFFE066
});
moneyTxt.anchor.set(0, 0.5);
game.addChild(moneyTxt);
// Initial layout
layoutCountersRow();
// --- Position time text and pause/resume/double speed buttons to the right of the money text ---
var timePauseSpacing = 180; // Further increased spacing to move timeTxt even more right
var pauseBtnSpacing = 80; // Further increased spacing to move pauseBtn even more right
// Place timeTxt to the right of moneyTxt
timeTxt.x = moneyTxt.x + moneyTxt.width + timePauseSpacing;
timeTxt.y = moneyTxt.y;
// Place pause, resume, and double speed buttons side by side to the right of timeTxt
var btnsStartX = timeTxt.x + timeTxt.width + pauseBtnSpacing + pauseBtn.bg.width / 2;
var btnsY = timeTxt.y;
pauseBtn.x = btnsStartX;
pauseBtn.y = btnsY;
resumeBtn.x = btnsStartX + pauseBtn.bg.width + 24;
resumeBtn.y = btnsY;
doubleSpeedBtn.x = btnsStartX + (pauseBtn.bg.width + 24) * 2;
doubleSpeedBtn.y = btnsY;
// Add to game after positioning
game.addChild(timeTxt);
game.addChild(pauseBtn);
game.addChild(resumeBtn);
game.addChild(doubleSpeedBtn);
// --- Action Buttons ---
// Button layout: stack vertically, bigger, with spacing
var btnW = 540;
var btnH = 220;
var btnSpacingY = 60;
var btnStartY = 900;
// Make Video Button
var makeVideoBtn = new GameButton();
makeVideoBtn.setButton('videoBtn', 'Record Video', "#fff", btnW, btnH);
makeVideoBtn.x = 2048 / 2;
// Move the record video button further down to fill the space of removed buttons
// Move the record video button 250 pixels higher
makeVideoBtn.y = btnStartY + 3 * (btnH + btnSpacingY) - 250;
// --- Loading Bar for Process ---
// (Removed: processBarBg and processBarFill, and their show/hide functions.)
// No independent loading bar on the main screen.
// --- Action Button Logic (time-based) ---
// Track if record video panel is open
var isRecordPanelOpen = false;
makeVideoBtn.action = function () {
if (timeProcess) {
return;
} // Only one process at a time
// Block recording if a video is in 'recorded' state and not finished (must edit first)
if (window.uploadedVideos) {
for (var i = 0; i < window.uploadedVideos.length; i++) {
if (window.uploadedVideos[i].state === "recorded" && !window.uploadedVideos[i].finished) {
// Optionally, show a message or flash the edit button
tween(editBtn, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 100,
onFinish: function onFinish() {
tween(editBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
return;
}
}
}
if (isRecordPanelOpen) {
return;
} // Prevent multiple panels
isRecordPanelOpen = true;
// Show a panel before starting the process
// Place the record panel visually inside the computerscreen asset
var panelBg = LK.getAsset('studioBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Set panel size to match the video list background, but not equal in pixel size
// Use the same width and height as videoListBg, but add a small difference so they are not exactly equal
panelBg.width = videoListBg.width + 24; // 12px wider on each side
panelBg.height = videoListBg.height - 18; // 18px shorter in height
panelBg.x = videoListBg.x + videoListBg.width / 2; // center on videoListBg
panelBg.y = videoListBg.y + videoListBg.height / 2; // center on videoListBg
panelBg.alpha = 0.98;
// --- Panel Title ---
var panelText = new Text2("Select Category & Title", {
size: 90,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
panelText.anchor.set(0.5, 0.5);
panelText.x = panelBg.x;
panelText.y = panelBg.y - panelBg.height / 2 + 120; // near top of panel
// --- Video Title Input ---
var titleInputBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0.5
});
titleInputBg.width = 1000;
titleInputBg.height = 130;
titleInputBg.x = panelBg.x - 180; // shift left to make space for random button
titleInputBg.y = panelText.y + 200; // more space below title
titleInputBg.alpha = 0.92;
var videoTitle = "";
var titleInputTxt = new Text2("Enter video title...", {
size: 72,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
titleInputTxt.anchor.set(0.5, 0.5);
titleInputTxt.x = titleInputBg.x;
titleInputTxt.y = titleInputBg.y;
// Simulate input: tap to edit, prompt for text
titleInputBg.down = function (x, y, obj) {
var prompt = LK.prompt ? LK.prompt : window.prompt; // fallback for dev
var val = prompt ? prompt("Enter video title:", videoTitle) : "";
if (typeof val === "string" && val.length > 0) {
videoTitle = val;
titleInputTxt.setText(videoTitle);
}
};
// --- Random Title Button ---
var randomBtn = new GameButton();
randomBtn.setButton('promoteBtn', 'Random', "#fff", 340, 120);
randomBtn.x = titleInputBg.x + titleInputBg.width / 2 + 200; // right of input with space
randomBtn.y = titleInputBg.y;
randomBtn.action = function () {
// Titles per category
var categoryTitles = {
"Vlog": ["My Daily Vlog", "Life Update", "A Day in My Life", "Morning Routine", "Evening Recap"],
"Challenge": ["Epic Challenge!", "24 Hour Challenge", "Impossible Task!", "Last To Leave", "Extreme Challenge"],
"Reaction": ["Reacting to Comments", "Reacting to Viral Videos", "First Time Watching", "Fan Reactions", "Surprising Reactions"],
"Tutorial": ["How To Edit Videos", "Beginner's Guide", "Pro Tips & Tricks", "Step by Step Tutorial", "Easy DIY"],
"Unboxing": ["Unboxing Surprise", "Mystery Box Unboxing", "Tech Unboxing", "Unboxing Haul", "First Impressions"],
"Gaming": ["Let's Play!", "Epic Gaming Moments", "Game Review", "Speedrun Attempt", "Funny Gaming Fails"],
"Music": ["My New Song", "Music Cover", "Behind the Music", "Songwriting Session", "Live Performance"],
"Comedy": ["Funny Moments", "Comedy Skit", "Prank Video", "Try Not To Laugh", "Bloopers & Outtakes"],
"Q&A": ["Q&A Special", "Answering Your Questions", "Ask Me Anything", "Subscriber Q&A", "Get To Know Me"],
"Other": ["Behind the Scenes", "Special Announcement", "Random Thoughts", "Channel Update", "What Happened Today"]
};
var cat = videoCategories[selectedCategoryIdx];
var titles = categoryTitles[cat] || ["My Daily Vlog", "Epic Challenge!", "Reacting to Comments", "24 Hours in My Studio", "Behind the Scenes", "Q&A Special", "Trying Viral Trends", "Unboxing Surprise", "Life Update", "Funny Moments"];
var idx = Math.floor(Math.random() * titles.length);
videoTitle = titles[idx];
titleInputTxt.setText(videoTitle);
};
// --- Video Category Buttons ---
var categoryBtnW = 340;
var categoryBtnH = 120;
var categoryBtnSpacingX = 40;
var categoryBtnSpacingY = 40;
var categoryBtns = [];
// Layout: fit as many as possible per row, then wrap
var maxRowWidth = panelBg.width - 120; // leave some margin
var maxPerRow = Math.floor((maxRowWidth + categoryBtnSpacingX) / (categoryBtnW + categoryBtnSpacingX));
if (maxPerRow < 1) {
maxPerRow = 1;
}
var startX = panelBg.x - (Math.min(maxPerRow, videoCategories.length) * (categoryBtnW + categoryBtnSpacingX) - categoryBtnSpacingX) / 2 + categoryBtnW / 2;
var startY = titleInputBg.y + 220; // more space below input+random
for (var i = 0; i < videoCategories.length; i++) {
(function (idx) {
var btn = new GameButton();
btn.setButton('editBtn', videoCategories[idx], "#fff", categoryBtnW, categoryBtnH);
var row = Math.floor(idx / maxPerRow);
var col = idx % maxPerRow;
btn.x = startX + col * (categoryBtnW + categoryBtnSpacingX);
btn.y = startY + row * (categoryBtnH + categoryBtnSpacingY);
btn.action = function () {
// Deselect all
for (var j = 0; j < categoryBtns.length; j++) {
// If trending, keep its highlight
if (j === trendingCategoryIdx) {
categoryBtns[j].bg.alpha = 0.95;
} else {
categoryBtns[j].bg.alpha = 0.7;
}
}
btn.bg.alpha = 1;
selectedCategoryIdx = idx;
};
// Highlight the first by default
if (i === 0) {
btn.bg.alpha = 1;
} else {
btn.bg.alpha = 0.7;
}
// Mark trending category visually
if (i === trendingCategoryIdx) {
btn.bg.alpha = 0.95;
// Add a "Trending" label above the button
var trendingTxt = new Text2("🔥 Trending", {
size: 48,
fill: "#ff0",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
trendingTxt.anchor.set(0.5, 1);
trendingTxt.x = btn.x;
trendingTxt.y = btn.y - categoryBtnH / 2 - 10;
btn.trendingTxt = trendingTxt;
}
categoryBtns.push(btn);
})(i);
}
// --- Confirm/Record Button ---
var confirmBtn = new GameButton();
// Make the button smaller and move it 50px up
confirmBtn.setButton('videoBtn', 'Record', "#fff", 480, 130);
confirmBtn.x = panelBg.x;
// Find the bottom Y of the last category button for spacing
var lastCategoryBtn = categoryBtns[categoryBtns.length - 1];
var categoryBtnsBottomY = lastCategoryBtn ? lastCategoryBtn.y + categoryBtnH / 2 : startY + categoryBtnH / 2;
confirmBtn.y = categoryBtnsBottomY + 150; // 50px higher than before
confirmBtn.action = function () {
// Remove panel
panelBg.destroy();
panelText.destroy();
confirmBtn.destroy();
titleInputBg.destroy();
titleInputTxt.destroy();
randomBtn.destroy();
closeBtn.destroy(); // Also destroy the close (X) button
// Destroy all category buttons
for (var i = 0; i < categoryBtns.length; i++) {
// Destroy trending label if exists
if (categoryBtns[i].trendingTxt) {
categoryBtns[i].trendingTxt.destroy();
}
categoryBtns[i].destroy();
}
isRecordPanelOpen = false;
// --- Add video to list immediately, in 'recording' state, before recording starts ---
if (!window.uploadedVideos) {
window.uploadedVideos = [];
}
var videoObj = {
title: videoTitle,
category: videoCategories[selectedCategoryIdx],
hour: 0,
totalHours: 7 * 24,
totalViews: 0,
totalMoney: 0,
totalSubs: 0,
trending: videoCategories[selectedCategoryIdx] === videoCategories[trendingCategoryIdx],
baseSubscribers: subscribers,
finished: false,
state: "recording",
// <--- show as recording
recordHoursLeft: 3,
totalRecordHours: 3,
// new: states are "recording", "recorded", "editing", "readyToPublish", "published"
editHoursLeft: 5,
publishReady: false
};
// Precompute total views to distribute realistically over 7 days
var minViewPercent = 0.01;
var maxViewPercent = 0.05;
var percent = minViewPercent + Math.random() * (maxViewPercent - minViewPercent);
var baseViews = Math.floor(videoObj.baseSubscribers * percent);
if (videoObj.baseSubscribers < 100) {
baseViews = 100 + Math.floor(Math.random() * 400);
}
if (videoObj.trending) {
baseViews = Math.floor(baseViews * 1.5);
}
videoObj.targetViews = baseViews;
videoObj.targetMoney = Math.floor(baseViews / 1000 * (3 + Math.random() * 2));
videoObj.targetSubs = Math.floor(baseViews / (200 + Math.floor(Math.random() * 101)));
videoObj.hourlyViews = [];
// Distribute views per hour: more at start, less at end (decay curve)
var decay = 0.012; // controls how fast views drop off
var total = 0;
for (var h = 0; h < videoObj.totalHours; h++) {
var rel = h / videoObj.totalHours;
var hourViews = Math.max(1, Math.round(baseViews * Math.exp(-decay * h)));
videoObj.hourlyViews.push(hourViews);
total += hourViews;
}
// Normalize to match targetViews
var scale = baseViews / total;
for (var h = 0; h < videoObj.hourlyViews.length; h++) {
videoObj.hourlyViews[h] = Math.floor(videoObj.hourlyViews[h] * scale);
}
window.uploadedVideos.push(videoObj);
videoCount += 1;
updateStats();
updateVideoLists();
// Start the process
timeProcess = {
type: 'record',
hoursLeft: 3,
total: 3,
category: videoCategories[selectedCategoryIdx],
title: videoTitle,
video: videoObj,
onFinish: function onFinish() {
LK.getSound('makeVideo').play();
// Mark video as recorded, ready for editing
videoObj.state = "recorded";
videoObj.recordHoursLeft = 0;
updateVideoLists();
// Animate button
tween(makeVideoBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 80,
onFinish: function onFinish() {
tween(makeVideoBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 80
});
}
});
// Removed winning condition at 1000 subscribers; game continues forever
}
};
// Removed call to undefined showProcessBar(0)
};
// --- Close (X) Button ---
var closeBtn = new Text2("×", {
size: 120,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
closeBtn.anchor.set(0.5, 0.5);
// Place at top right of panel, with margin
closeBtn.x = panelBg.x + panelBg.width / 2 - 80;
closeBtn.y = panelBg.y - panelBg.height / 2 + 80;
closeBtn.interactive = true;
closeBtn.buttonMode = true;
closeBtn.down = function () {
panelBg.destroy();
panelText.destroy();
confirmBtn.destroy();
closeBtn.destroy();
titleInputBg.destroy();
titleInputTxt.destroy();
randomBtn.destroy();
// Destroy all category buttons
for (var i = 0; i < categoryBtns.length; i++) {
// Destroy trending label if exists
if (categoryBtns[i].trendingTxt) {
categoryBtns[i].trendingTxt.destroy();
}
categoryBtns[i].destroy();
}
isRecordPanelOpen = false;
};
// Add all panel elements to game
game.addChild(panelBg);
game.addChild(panelText);
game.addChild(titleInputBg);
game.addChild(titleInputTxt);
game.addChild(randomBtn);
game.addChild(closeBtn);
// Add all category buttons
for (var i = 0; i < categoryBtns.length; i++) {
game.addChild(categoryBtns[i]);
// If trending label exists, add it to game
if (categoryBtns[i].trendingTxt) {
game.addChild(categoryBtns[i].trendingTxt);
}
}
game.addChild(confirmBtn);
};
// (Removed: makeVideoBtn from main screen, now triggered by recordVideoBtn next to videos button)
// (Removed: manual y-positioning of subIcon/subTxt and moneyIcon/moneyTxt; handled by layoutCountersRow)
// Removed undefined energyBar and energyTxt
// --- GUI: Timer/Score (use subscribers as score) ---
// Removed giant numbers next to the subscriber counter
// --- Helper Functions ---
function formatNumber(num) {
if (num < 1000) {
return "" + num;
}
if (num < 1000000) {
var k = num / 1000;
if (k % 1 === 0) {
return k + "k";
}
return k.toFixed(1).replace(/\.0$/, "") + "k";
}
var m = num / 1000000;
if (m % 1 === 0) {
return m + "m";
}
return m.toFixed(1).replace(/\.0$/, "") + "m";
}
function updateStats() {
// --- Helper for green increase text ---
function showGreenIncrease(textObj, increase, prefix) {
if (!increase || increase <= 0) {
return;
}
var plusText = new Text2("+" + formatNumber(increase), {
size: 48,
fill: 0x00FF44,
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
plusText.anchor.set(0, 0.5);
// Place to the right of the number
plusText.x = textObj.x + textObj.width + 16;
plusText.y = textObj.y;
game.addChild(plusText);
tween(plusText, {
y: plusText.y - 40,
alpha: 0
}, {
duration: 1200,
easing: tween.cubicOut,
onFinish: function onFinish() {
plusText.destroy();
}
});
}
// Subscribers
if (typeof updateStats.lastSubValue !== "number") {
updateStats.lastSubValue = subscribers;
}
var subIncrease = subscribers - updateStats.lastSubValue;
subTxt.setText(formatNumber(subscribers));
if (subIncrease > 0) {
showGreenIncrease(subTxt, subIncrease, "");
}
updateStats.lastSubValue = subscribers;
// Views
if (typeof updateStats.lastViewValue !== "number") {
updateStats.lastViewValue = viewCount;
}
var viewIncrease = viewCount - updateStats.lastViewValue;
viewTxt.setText(formatNumber(viewCount));
if (viewIncrease > 0) {
showGreenIncrease(viewTxt, viewIncrease, "");
}
updateStats.lastViewValue = viewCount;
// Money
if (typeof updateStats.lastMoneyValue !== "number") {
updateStats.lastMoneyValue = money;
}
var moneyIncrease = money - updateStats.lastMoneyValue;
// Truncate money to 2 decimal digits for display
var moneyDisplay = Math.floor(money * 100) / 100;
moneyTxt.setText(formatNumber(moneyDisplay));
if (moneyIncrease > 0) {
// Truncate moneyIncrease to 2 decimal digits for display
var moneyIncreaseDisplay = Math.floor(moneyIncrease * 100) / 100;
showGreenIncrease(moneyTxt, moneyIncreaseDisplay, "");
}
updateStats.lastMoneyValue = money;
// Enable/disable buttons based on process and resources
makeVideoBtn.setEnabled(!timeProcess);
// --- Achievements ---
if (!updateStats.milestones) {
updateStats.milestones = {};
}
// Subscriber milestones
var milestones = [10, 25, 50, 100, 250, 500, 750, 1000, 2500, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000];
for (var i = 0; i < milestones.length; i++) {
var m = milestones[i];
if (subscribers >= m && !updateStats.milestones["subs" + m]) {
updateStats.milestones["subs" + m] = true;
var ach = new Text2("Milestone: " + m + " Subs!", {
size: 110,
fill: "#ff0",
stroke: "#000",
strokeThickness: 12,
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 12,
dropShadowDistance: 4
});
ach.anchor.set(0.5, 0.5);
ach.x = 2048 / 2;
ach.y = 400 + i * 80;
game.addChild(ach);
tween(ach, {
alpha: 0,
y: ach.y - 100
}, {
duration: 1800,
onFinish: function onFinish() {
ach.destroy();
}
});
}
}
// View milestones
var viewMilestones = [1000, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000, 5000000, 10000000];
for (var i = 0; i < viewMilestones.length; i++) {
var m = viewMilestones[i];
if (viewCount >= m && !updateStats.milestones["views" + m]) {
updateStats.milestones["views" + m] = true;
var ach = new Text2("Milestone: " + formatNumber(m) + " Views!", {
size: 110,
fill: 0x00E0FF,
stroke: "#000",
strokeThickness: 12,
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 12,
dropShadowDistance: 4
});
ach.anchor.set(0.5, 0.5);
ach.x = 2048 / 2;
ach.y = 400 + (i + milestones.length) * 80;
game.addChild(ach);
tween(ach, {
alpha: 0,
y: ach.y - 100
}, {
duration: 1800,
onFinish: function onFinish() {
ach.destroy();
}
});
}
}
// Money milestones
var moneyMilestones = [100, 500, 1000, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000];
for (var i = 0; i < moneyMilestones.length; i++) {
var m = moneyMilestones[i];
if (money >= m && !updateStats.milestones["money" + m]) {
updateStats.milestones["money" + m] = true;
var ach = new Text2("Milestone: $" + formatNumber(m) + " Earned!", {
size: 110,
fill: 0xFA4B00,
stroke: "#000",
strokeThickness: 12,
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 12,
dropShadowDistance: 4
});
ach.anchor.set(0.5, 0.5);
ach.x = 2048 / 2;
ach.y = 400 + (i + milestones.length + viewMilestones.length) * 80;
game.addChild(ach);
tween(ach, {
alpha: 0,
y: ach.y - 100
}, {
duration: 1800,
onFinish: function onFinish() {
ach.destroy();
}
});
}
}
}
// --- Video List UI Update ---
// --- Time Update ---
function updateTimeDisplay() {
var h = gameHour;
var hStr = (h < 10 ? "0" : "") + h + ":00";
timeTxt.setText("Day " + gameDay + ", " + hStr);
}
// --- Process Update ---
function updateProcessBar() {
// No independent loading bar on the main screen.
}
// --- Time Timer ---
if (timeTimer) {
LK.clearInterval(timeTimer);
}
// Helper function to process one hour of time advancement
function processOneHour() {
// Advance time
gameHour += 1;
if (gameHour >= 24) {
gameHour = 0;
gameDay += 1;
// Record daily stats exactly once per day
recordDailyStats();
// Check if it's time to change trending category
// Trending category changes a random number of times every 7 to 30 days
if (typeof trendingCategoryNextChangeDay === "undefined") {
trendingCategoryNextChangeDay = trendingCategoryDay + 7 + Math.floor(Math.random() * 24); // 7-30 days
}
if (gameDay >= trendingCategoryNextChangeDay) {
updateTrendingCategory();
trendingCategoryNextChangeDay = gameDay + 7 + Math.floor(Math.random() * 24); // 7-30 days
}
}
updateTimeDisplay();
// Process logic
if (timeProcess) {
timeProcess.hoursLeft -= 1;
updateProcessBar();
if (timeProcess.hoursLeft <= 0) {
var finish = timeProcess.onFinish;
// If editing, update video state
if (timeProcess.type === "edit" && timeProcess.video) {
timeProcess.video.state = "readyToPublish";
timeProcess.video.publishReady = true;
}
timeProcess = null;
updateProcessBar();
updateStats();
updateVideoLists();
if (typeof finish === "function") {
finish();
}
}
}
// Per-hour video view/money/subscriber accrual
if (window.uploadedVideos) {
for (var v = 0; v < window.uploadedVideos.length; v++) {
var vid = window.uploadedVideos[v];
// Only accrue views, money, and subs if published and not finished
if (vid.state === "published" && vid.hour < vid.totalHours) {
var viewsThisHour = vid.hourlyViews[vid.hour] || 0;
// --- Add promote campaign views to this video if any active promote campaigns exist ---
// Find all active promote campaigns for this hour and add their views to this video if the campaign is running
if (window.activePromotes && window.activePromotes.length > 0) {
for (var pi = 0; pi < window.activePromotes.length; pi++) {
var p = window.activePromotes[pi];
if (p.finished) continue;
var promoteDay = gameDay - p.startDay;
var promoteHour = gameHour;
if (promoteDay >= 0 && promoteDay < p.days) {
var promoteViewsThisHour = p.viewsPerHour[promoteDay][promoteHour] || 0;
viewsThisHour += promoteViewsThisHour;
}
}
}
// --- NEW: Instantly update subscribers and money per view ---
// 1) For every 1 view, 1% chance to gain a subscriber (instantly)
// 2) For every 100 views, earn 0.05 money (instantly) -- reduced
var subsThisHour = 0;
var moneyThisHour = 0;
for (var i = 0; i < viewsThisHour; i++) {
if (Math.random() < 0.01) {
// 1% chance per view
subsThisHour += 1;
}
}
// Each viewer gives a random amount between 0.005 and 0.02 (reduced)
moneyThisHour = 0;
for (var vi = 0; vi < viewsThisHour; vi++) {
moneyThisHour += 0.005 + Math.random() * 0.015;
}
vid.totalViews += viewsThisHour;
vid.totalMoney += moneyThisHour;
vid.totalSubs += subsThisHour;
viewCount += viewsThisHour;
money += moneyThisHour;
subscribers += subsThisHour;
vid.hour++;
// Clamp to target on last hour
if (vid.hour === vid.totalHours) {
// Remove the video from the video list when publishing is complete
window.uploadedVideos.splice(v, 1);
v--; // Adjust index since we removed an item
continue; // Skip further processing for this video
}
}
}
}
// --- Promote Campaigns: process per hour ---
if (window.activePromotes && window.activePromotes.length > 0) {
for (var pi = window.activePromotes.length - 1; pi >= 0; pi--) {
var p = window.activePromotes[pi];
// Determine which day/hour of campaign we are in
var promoteDay = gameDay - p.startDay;
var promoteHour = gameHour;
if (promoteDay >= 0 && promoteDay < p.days && !p.finished) {
// Show to this hour's people
var viewsThisHour = p.viewsPerHour[promoteDay][promoteHour] || 0;
p.shownPerHour[promoteDay][promoteHour] = viewsThisHour;
// Conversion rate: use p.subRate
var subsThisHour = 0;
for (var vi = 0; vi < viewsThisHour; vi++) {
if (Math.random() < p.subRate) subsThisHour++;
}
p.subsGained += subsThisHour;
subscribers += subsThisHour;
viewCount += viewsThisHour;
// Track for stats
if (!p.subsPerDay[promoteDay]) p.subsPerDay[promoteDay] = 0;
p.subsPerDay[promoteDay] += subsThisHour;
if (!p.viewsPerDay[promoteDay]) p.viewsPerDay[promoteDay] = 0;
p.viewsPerDay[promoteDay] += viewsThisHour;
// --- Update promote in-panel label values ---
var totalHours = p.days * 24;
var spentPerHour = p.amount / totalHours;
p.spentSoFar += spentPerHour;
p.viewsSoFar += viewsThisHour;
if (typeof p.updatePromoteListLabel === "function") {
p.updatePromoteListLabel();
}
}
// Mark as finished if campaign is over
if (gameDay > p.startDay + p.days - 1) {
p.finished = true;
}
// Remove finished promotes after last day
if (p.finished && gameDay > p.lastDay + 1) {
// Remove label from panel
if (p._promoteListLabel) {
for (var li = 0; li < p._promoteListLabel.length; li++) {
if (p._promoteListLabel[li] && typeof p._promoteListLabel[li].destroy === "function") {
p._promoteListLabel[li].destroy();
}
}
p._promoteListLabel = null;
}
window.activePromotes.splice(pi, 1);
updatePromoteListDisplay();
}
}
}
updateStats();
updateVideoLists();
}
// Timer logic for normal and double speed
var doubleSpeedTimer = null;
function setTimeTimer() {
if (timeTimer) {
LK.clearInterval(timeTimer);
timeTimer = null;
}
if (doubleSpeedTimer) {
LK.clearInterval(doubleSpeedTimer);
doubleSpeedTimer = null;
}
// Normal speed: 1 hour every 1000ms
if (timeSpeed === 1) {
timeTimer = LK.setInterval(function () {
if (timeSpeed !== 1 || isTimePaused) return;
processOneHour();
}, 1000);
}
// Double speed: 1 hour every 500ms
else if (timeSpeed === 2) {
doubleSpeedTimer = LK.setInterval(function () {
if (timeSpeed !== 2 || isTimePaused) return;
processOneHour();
}, 500);
}
// Paused: do nothing
}
setTimeTimer();
// Patch time control buttons to call setTimeTimer when speed changes
var oldUpdateTimeControlButtons = updateTimeControlButtons;
updateTimeControlButtons = function updateTimeControlButtons() {
oldUpdateTimeControlButtons();
setTimeTimer();
};
// --- Game Update Loop ---
game.update = function () {
// Nothing needed for now, all logic is event/click based
};
// --- Touch/Drag Handling (no drag needed, but block top left 100x100) ---
game.down = function (x, y, obj) {
// Prevent accidental clicks in top left
if (x < 100 && y < 100) {
return;
}
};
game.move = function (x, y, obj) {};
game.up = function (x, y, obj) {};
// --- Initialize UI ---
updateStats();
// Hide video list and background by default at game start
videoListBg.visible = false;
videoListContainer.visible = false;
// --- Tutorial Items (bottom left) ---
var tutorialItems = ["1. Record your video", "2. Edit your video", "3. Publish your video", "4. Gain viewers and subscribers", "5. Promote and grow your channel!"];
var tutorialTexts = [];
var tutorialStartX = 40;
var tutorialFontSize = 64;
var tutorialSpacing = 80;
var tutorialStartY = 2732 - 60 - tutorialItems.length * tutorialSpacing; // 60px margin from bottom
for (var i = 0; i < tutorialItems.length; i++) {
var tutTxt = new Text2(tutorialItems[i], {
size: tutorialFontSize,
fill: "#fff",
font: "Arial, Helvetica, sans-serif",
dropShadow: true,
dropShadowColor: "#222",
dropShadowBlur: 8,
dropShadowDistance: 2
});
tutTxt.anchor.set(0, 0);
tutTxt.x = tutorialStartX;
tutTxt.y = tutorialStartY + i * tutorialSpacing;
game.addChild(tutTxt);
tutorialTexts.push(tutTxt);
}
// --- Promote Stats Panel (hourly breakdown) ---
function showPromoteStatsPanel(promoteIdx) {
if (!window.activePromotes || !window.activePromotes[promoteIdx]) return;
var p = window.activePromotes[promoteIdx];
// Panel background
var promoteStatsBg = LK.getAsset('studioBg', {
anchorX: 0.5,
anchorY: 0.5
});
promoteStatsBg.width = 1200;
promoteStatsBg.height = 1200;
promoteStatsBg.x = 2048 / 2;
promoteStatsBg.y = 2732 / 2;
promoteStatsBg.alpha = 0.98;
// Title
var promoteStatsTitle = new Text2("Promote Campaign Details", {
size: 70,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
promoteStatsTitle.anchor.set(0.5, 0.5);
promoteStatsTitle.x = promoteStatsBg.x;
promoteStatsTitle.y = promoteStatsBg.y - promoteStatsBg.height / 2 + 80;
// Table header
var headerTxt = new Text2("Day | Hour | Views | Subs", {
size: 44,
fill: "#0ff",
font: "Arial, Helvetica, sans-serif"
});
headerTxt.anchor.set(0.5, 0.5);
headerTxt.x = promoteStatsBg.x;
headerTxt.y = promoteStatsTitle.y + 80;
// Table rows (show up to 24 hours for each day)
var tableLabels = [];
var startY = headerTxt.y + 60;
var rowH = 38;
var maxRows = 20;
var shownRows = 0;
for (var d = 0; d < p.days && shownRows < maxRows; d++) {
for (var h = 0; h < 24 && shownRows < maxRows; h++) {
var views = p.shownPerHour[d] ? p.shownPerHour[d][h] : 0;
var subs = 0;
// Estimate subs for this hour (approximate, since we don't store per hour)
if (views > 0) {
subs = Math.floor(views * p.subRate);
}
var rowTxt = new Text2(d + 1 + " | " + (h < 10 ? "0" : "") + h + ":00 | " + views + " | " + subs, {
size: 36,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
rowTxt.anchor.set(0.5, 0.5);
rowTxt.x = promoteStatsBg.x;
rowTxt.y = startY + shownRows * rowH;
tableLabels.push(rowTxt);
shownRows++;
}
}
// Close button
var closeStatsBtn = new GameButton();
closeStatsBtn.setButton('editBtn', 'Close', "#fff", 320, 90);
closeStatsBtn.x = promoteStatsBg.x;
closeStatsBtn.y = promoteStatsBg.y + promoteStatsBg.height / 2 - 80;
closeStatsBtn.action = function () {
promoteStatsBg.destroy();
promoteStatsTitle.destroy();
headerTxt.destroy();
closeStatsBtn.destroy();
for (var i = 0; i < tableLabels.length; i++) tableLabels[i].destroy();
};
// Add to game
game.addChild(promoteStatsBg);
game.addChild(promoteStatsTitle);
game.addChild(headerTxt);
for (var i = 0; i < tableLabels.length; i++) game.addChild(tableLabels[i]);
game.addChild(closeStatsBtn);
}
// --- Statistics Section UI ---
// Data arrays for stats (one entry per day)
var statsViewsPerDay = [];
var statsSubsPerDay = [];
var statsMoneyPerDay = [];
var statsLastDay = 0;
// Statistics overlay container (hidden by default)
var statsOverlay = new Container();
statsOverlay.visible = false;
statsOverlay.x = 0;
statsOverlay.y = 0;
game.addChild(statsOverlay);
// Overlay background
// Move the statistics overlay 250px up, crop 10px from left/right, 200px from top/bottom
var statsBgWidth = 1950 - 20; // 10px left, 10px right
var statsBgHeight = 1600 - 400; // 200px top, 200px bottom
var statsBg = LK.getAsset('studioBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 450
});
statsBg.width = statsBgWidth;
statsBg.height = statsBgHeight;
statsBg.alpha = 0.98;
statsOverlay.addChild(statsBg);
// Title removed as requested
// --- Graph Toggle Buttons ---
var statTypes = [{
key: "views",
label: "Views",
color: 0x00e0ff,
icon: "viewersicon"
}, {
key: "subs",
label: "Subscribers",
color: 0xffe066,
icon: "subIcon"
}, {
key: "money",
label: "Money",
color: 0xfa4b00,
icon: "moneyIcon"
}];
var statDataMap = {
views: statsViewsPerDay,
subs: statsSubsPerDay,
money: statsMoneyPerDay
};
var statLabelMap = {
views: "Views per Day",
subs: "Subscribers per Day",
money: "Money Earned per Day"
};
var statIconMap = {
views: "viewersicon",
subs: "subIcon",
money: "moneyIcon"
};
var statColorMap = {
views: 0x00e0ff,
subs: 0xffe066,
money: 0xfa4b00
};
var selectedStatType = "views";
var statToggleBtns = [];
var toggleBtnW = 260;
var toggleBtnH = 80;
var toggleBtnSpacing = 36;
var toggleBtnStartX = 2048 / 2 - (toggleBtnW * 1.5 + toggleBtnSpacing);
// Yeni statsBg yüksekliğine göre toggle butonlarını hizala
var toggleBtnY = statsBg.y - statsBg.height / 2 + 120;
for (var i = 0; i < statTypes.length; i++) {
(function (idx) {
var btn = new GameButton();
btn.setButton('editBtn', statTypes[idx].label, "#fff", toggleBtnW, toggleBtnH);
// Reduce label font size for statistics top buttons
if (btn.label) {
if (btn.label.style && typeof btn.label.style.size !== "undefined") {
btn.label.style.size = 44;
btn.label.dirty = true;
} else if (typeof btn.label.setStyle === "function") {
btn.label.setStyle({
size: 44
});
}
}
btn.x = toggleBtnStartX + idx * (toggleBtnW + toggleBtnSpacing);
btn.y = toggleBtnY;
btn.action = function () {
// Deselect all
for (var j = 0; j < statToggleBtns.length; j++) {
statToggleBtns[j].bg.alpha = 0.7;
}
btn.bg.alpha = 1;
selectedStatType = statTypes[idx].key;
updateStatsGraphSingle();
};
// Highlight first by default
btn.bg.alpha = i === 0 ? 1 : 0.7;
statToggleBtns.push(btn);
statsOverlay.addChild(btn);
})(i);
}
// --- Single Graph Area ---
var graphW = 1200;
var graphH = 500;
var graphStartX = (2048 - graphW) / 2;
var graphStartY = statsBg.y - statsBg.height / 2 + 220;
// Helper to draw a single stat graph
function drawStatSingleGraph(container, data, color, iconAssetId, label) {
if (!container.graphNodes) container.graphNodes = [];
// Remove previous graph
for (var i = 0; i < container.graphNodes.length; i++) {
container.graphNodes[i].destroy();
}
container.graphNodes = [];
// Card background
var cardBg = LK.getAsset('loadingbarempty', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: graphStartY
});
cardBg.width = graphW + 120;
cardBg.height = graphH + 100;
cardBg.alpha = 0.93;
container.addChild(cardBg);
container.graphNodes.push(cardBg);
// Draw icon
var icon = LK.getAsset(iconAssetId, {
anchorX: 0.5,
anchorY: 0.5,
x: graphStartX - 100,
y: graphStartY + 60 + graphH / 2
});
icon.width = 120;
icon.height = 120;
container.addChild(icon);
container.graphNodes.push(icon);
// Draw label
var labelTxt = new Text2(label, {
size: 60,
fill: "#fff",
font: "Arial, Helvetica, sans-serif"
});
labelTxt.anchor.set(0, 0.5);
labelTxt.x = graphStartX;
labelTxt.y = graphStartY + 40;
container.addChild(labelTxt);
container.graphNodes.push(labelTxt);
// Find max value for scaling
var maxVal = 1;
for (var i = 0; i < data.length; i++) {
if (data[i] > maxVal) maxVal = data[i];
}
// Draw line graph: connect points with rectangles (simulate lines)
var prevX = null,
prevY = null;
for (var i = 0; i < data.length; i++) {
var x0 = graphStartX + i / Math.max(1, data.length - 1) * graphW;
var y0 = graphStartY + 100 + graphH - data[i] / maxVal * (graphH - 20);
// Draw a small circle at each data point
var point = LK.getAsset('loadingbarfull', {
anchorX: 0.5,
anchorY: 0.5,
x: x0,
y: y0
});
point.width = 18;
point.height = 18;
point.tint = color;
container.addChild(point);
container.graphNodes.push(point);
// Draw value label every 5 days or last
if ((i % 5 === 0 || i === data.length - 1) && data[i] > 0) {
var displayValue = data[i];
// If this is the money graph, format to 2 decimal places
if (selectedStatType === "money") {
displayValue = Math.floor(data[i] * 100) / 100;
// Always show 2 decimals for money
displayValue = displayValue.toFixed(2);
}
var valTxt = new Text2("" + displayValue, {
size: 36,
fill: "#fff"
});
valTxt.anchor.set(0.5, 1);
valTxt.x = x0;
valTxt.y = y0 - 8;
container.addChild(valTxt);
container.graphNodes.push(valTxt);
}
// Draw a "line" between previous and current point using a thin rectangle
if (prevX !== null && prevY !== null) {
var dx = x0 - prevX;
var dy = y0 - prevY;
var dist = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
var line = LK.getAsset('loadingbarfull', {
anchorX: 0,
anchorY: 0.5,
x: prevX,
y: prevY
});
line.width = dist;
line.height = 8;
line.tint = color;
line.rotation = angle;
container.addChild(line);
container.graphNodes.push(line);
}
prevX = x0;
prevY = y0;
}
}
// Draw the selected graph
function updateStatsGraphSingle() {
var key = selectedStatType;
var data = statDataMap[key];
var color = statColorMap[key];
var icon = statIconMap[key];
var label = statLabelMap[key];
drawStatSingleGraph(statsOverlay, data, color, icon, label);
}
// Close button for stats overlay
var statsCloseBtn = new GameButton();
statsCloseBtn.setButton('editBtn', 'Close', "#fff", 320, 90);
statsCloseBtn.x = 2048 / 2;
statsCloseBtn.y = statsBg.y + statsBg.height / 2 - 80;
statsCloseBtn.action = function () {
statsOverlay.visible = false;
};
statsOverlay.addChild(statsCloseBtn);
// Statistics Section Button removed with navigation bar
// --- Track stats per day ---
// Call this at the end of each day
function recordDailyStats() {
// Only record once per day
if (statsLastDay === gameDay) {
return;
}
statsLastDay = gameDay;
statsViewsPerDay.push(viewCount);
statsSubsPerDay.push(subscribers);
statsMoneyPerDay.push(money);
}
// Record stats for day 1 at game start
recordDailyStats();
// Define updatePromoteListDisplay in global scope to avoid not defined error
function updatePromoteListDisplay() {
// This is a stub to avoid not defined error if called outside promote panel
// The real implementation is inside the promote panel logic
} ===================================================================
--- original.js
+++ change.js
@@ -154,10 +154,10 @@
/****
* Game Code
****/
-// --- Trending Category State ---
// --- Video Categories (must be defined before use in updateTrendingCategory) ---
+// --- Trending Category State ---
var videoCategories = ["Vlog", "Challenge", "Reaction", "Tutorial", "Unboxing", "Gaming", "Music", "Comedy", "Q&A", "Other"];
var selectedCategoryIdx = 0;
// Studio background (simple box for now)
// --- Game State Variables ---
@@ -856,11 +856,11 @@
estSubs = 0,
estConv = 0,
estSubRate = 0;
function updateEstimates() {
- // Each $1 = 500-1500 views
- var minViews = Math.floor(promoteAmount * 500);
- var maxViews = Math.floor(promoteAmount * 1500);
+ // Each $1 = 250-750 views (reduced)
+ var minViews = Math.floor(promoteAmount * 250);
+ var maxViews = Math.floor(promoteAmount * 750);
estViews = minViews + Math.floor(Math.random() * (maxViews - minViews + 1));
// Conversion rate: 0.1% - 2% (spread), 1-1.5% if spread over >1 day
if (promoteDays === 1) {
estSubRate = 0.001 + Math.random() * 0.019; // 0.1% - 2%
@@ -921,10 +921,10 @@
spentSoFar: 0,
viewsSoFar: 0,
summaryPanel: null,
summaryLabels: [],
- minViews: Math.floor(promoteAmount * 500),
- maxViews: Math.floor(promoteAmount * 1500)
+ minViews: Math.floor(promoteAmount * 250),
+ maxViews: Math.floor(promoteAmount * 750)
};
// Distribute views per day
var perDay = Math.floor(estViews / promoteDays);
var remain = estViews - perDay * promoteDays;
@@ -2036,21 +2036,21 @@
}
}
// --- NEW: Instantly update subscribers and money per view ---
// 1) For every 1 view, 1% chance to gain a subscriber (instantly)
- // 2) For every 100 views, earn 0.1 money (instantly)
+ // 2) For every 100 views, earn 0.05 money (instantly) -- reduced
var subsThisHour = 0;
var moneyThisHour = 0;
for (var i = 0; i < viewsThisHour; i++) {
if (Math.random() < 0.01) {
// 1% chance per view
subsThisHour += 1;
}
}
- // Each viewer gives a random amount between 0.01 and 0.05
+ // Each viewer gives a random amount between 0.005 and 0.02 (reduced)
moneyThisHour = 0;
for (var vi = 0; vi < viewsThisHour; vi++) {
- moneyThisHour += 0.01 + Math.random() * 0.04;
+ moneyThisHour += 0.005 + Math.random() * 0.015;
}
vid.totalViews += viewsThisHour;
vid.totalMoney += moneyThisHour;
vid.totalSubs += subsThisHour;
subscriber icon 2d. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
money icon 2d. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
solid grey colour background for panel. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
viewers icon for a mobile game. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make bigger this monitor
please to this white color
white play button solid white color. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
double speed icon for mobile games. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat. no text. only white color.
2d phone for mobile games. modern phone. looks good but phone is one color, phone's screen one color. Let it be completely 2-dimensional and not look like 3-dimensional. There should be a mute button and small volume up and down and hang up buttons on the sides of the phone.. In-Game asset. 2d. High contrast. No shadows - Fill the entire screen with a light gray color. - The outer cover color of the phone should be dark gray.
youtube button logo. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
white background rounded corners. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat white color. all white color no border.
playstore logo. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
editing application logo. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
çöp kutusu logosu fakat kırmızı arka planlı (çöp kutusu logosu beyaz renkte olacak). In-Game asset. 2d. High contrast. No shadows
kırmızıya boya
beyaza boya
maviye boya
istatistik logosu. In-Game asset. 2d. High contrast. No shadows
reklam logosu herhangi bir yazı olmasın. In-Game asset. 2d. High contrast. No shadows
record video logo with not text. In-Game asset. 2d. High contrast. No shadows
finans logosu. In-Game asset. 2d. High contrast. No shadows
youtube studio logo with no text only logo. In-Game asset. 2d. High contrast. No shadows
create youtube channel avatar cartoon 2d. In-Game asset. 2d. High contrast. No shadows
youtube channel logo. In-Game asset. 2d. High contrast. No shadows
"rastgele" ikonu, beyaz renginde olacak.. In-Game asset. 2d. High contrast. No shadows
youtube thumbnail for vlog. 2d. High contrast. No shadows
kilit ikonu beyaz. In-Game asset. 2d. High contrast. No shadows