Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
release/
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,55 @@
# My-projects
# Neon Forecourt

A desktop-ready gas station simulator with stylized 3D arcade visuals, shifting neon lights, and a quick score-chasing management loop.

## Features

- Three playable pump lanes with incoming AI cars
- Walkable station attendant using WASD or arrow keys
- Hold-to-fuel gameplay with combo bonuses and customer patience
- Fuel-stock management with fast tanker refills
- Bloom-heavy dusk lighting, neon signage, and low-poly 3D scenery

## Controls

- `WASD` / arrow keys: move
- Drag mouse: orbit camera
- Mouse wheel: zoom
- `Hold E`: fuel the car at the nearest waiting pump
- `Shift`: sprint
- `R`: buy an instant tanker refill
- `Enter`: restart after the shift ends

## Run in the browser

```bash
npm install
npm run dev
```

Build for production:

```bash
npm run build
```

## Run as a desktop app

Launch the standalone Electron version:

```bash
npm install
npm run desktop
```

Create a packaged desktop build for your current OS:

```bash
npm run desktop:pack
```

Create installable output in `release/`:

```bash
npm run desktop:dist
```
72 changes: 72 additions & 0 deletions electron/main.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const { app, BrowserWindow } = require("electron");
const path = require("node:path");
const fs = require("node:fs");
const { pathToFileURL } = require("node:url");

const appDataRoot = app.getPath("appData");
const userDataDir = path.join(appDataRoot, "Neon Forecourt");
const sessionDataDir = path.join(userDataDir, "SessionData");
const cacheDir = path.join(userDataDir, "Cache");

fs.mkdirSync(userDataDir, { recursive: true });
fs.mkdirSync(sessionDataDir, { recursive: true });
fs.mkdirSync(cacheDir, { recursive: true });

app.setPath("userData", userDataDir);
app.setPath("sessionData", sessionDataDir);
app.commandLine.appendSwitch("ignore-gpu-blocklist");
app.commandLine.appendSwitch("enable-gpu-rasterization");
app.commandLine.appendSwitch("enable-zero-copy");
app.commandLine.appendSwitch("disk-cache-dir", cacheDir);

function resolveRendererEntry() {
const builtIndex = path.join(__dirname, "..", "dist", "index.html");
const fallbackIndex = path.join(__dirname, "..", "index.html");
const target = fs.existsSync(builtIndex) ? builtIndex : fallbackIndex;
return pathToFileURL(target).toString();
}

function createWindow() {
const mainWindow = new BrowserWindow({
width: 1600,
height: 960,
minWidth: 1180,
minHeight: 760,
show: false,
backgroundColor: "#07101d",
autoHideMenuBar: true,
title: "Neon Forecourt",
webPreferences: {
contextIsolation: true,
sandbox: true,
backgroundThrottling: false,
spellcheck: false,
},
});

mainWindow.once("ready-to-show", () => {
mainWindow.show();
});

mainWindow.loadURL(resolveRendererEntry());

if (process.env.ELECTRON_OPEN_DEVTOOLS === "1") {
mainWindow.webContents.openDevTools({ mode: "detach" });
}
}

app.whenReady().then(() => {
createWindow();

app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});

app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
Loading