Флеш айзек на айфоне
запустил старого айзека в браузере на локальном сервере который скомпилировал прямо на айфоне и написал через дипсик за 2 минуты. для запуска использовал ish как типа линукс в айфоне
сам айзек очевидно написан на флеше поэтому просто нужно было закинуть в локальный сервер скрипты от ruffle который как раз запускает флеш игры в браузере
а ну еще пришлось написать элементы управления тк айзек никогда не был задуман для сенсорного управления (тем более на мобильном браузере) поэтому заставляем тот же ИИ написать экранные кнопки
и это кст не демка. зачем нашел прям фул образ с dlc даже
вот код кнопок и вебсервиса
(function() {
'use strict';
function pressKey(kEvent, kName, kCode, kNumber) {
if(document.querySelector("ruffle-player") != null) {
var ruffleSelector = "ruffle-player";
} else if(document.querySelector("ruffle-embed") != null) {
var ruffleSelector = "ruffle-embed";
} else if(document.querySelector("#player") != null) {
var ruffleSelector = "#player";
} else {
return false;
}
document.querySelector(ruffleSelector).focus();
document.querySelector(ruffleSelector).dispatchEvent(new KeyboardEvent(kEvent, {
key: kName,
code: kCode,
keyCode: kNumber,
which: kNumber,
bubbles: true
}));
return false;
}
function addKeyboard() {
var html = `<style>
#virtualKb {
position: fixed;
width: 100%;
height: 260px;
left: 0px;
bottom: 0px;
z-index: 9999;
background-color: transparent;
pointer-events: none;
}
#keyboardLeft {
position: absolute;
top: 10px;
left: 10px;
}
#keyboardRight {
position: absolute;
top: 10px;
right: 20px;
}
#keyboardCenter {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 20px;
}
#arrowKeys {
position: relative;
width: auto;
height: auto;
left: -164px;
}
#wasdKeys {
position: relative;
width: auto;
height: auto;
}
#upKey, #downKey, #leftKey, #rightKey,
#wKey, #aKey, #sKey, #dKey,
#spaceBar, #eKey {
position: absolute;
background: rgba(51, 51, 51, 0.7);
border: 2px solid #eee;
color: #eee;
font-weight: bold;
font-size: 18px;
padding: 4px;
pointer-events: all;
cursor: pointer;
border-radius: 5px;
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
}
#spaceBar, #eKey {
position: relative;
width: 80px;
height: 80px;
border-radius: 50%;
}
#upKey {
top: 0px;
left: 60px;
}
#downKey {
top: 120px;
left: 60px;
}
#leftKey {
top: 60px;
left: 0px;
}
#rightKey {
top: 60px;
left: 120px;
}
#wKey {
top: 0px;
left: 60px;
}
#sKey {
top: 120px;
left: 60px;
}
#aKey {
top: 60px;
left: 0px;
}
#dKey {
top: 60px;
left: 120px;
}
</style>
<div id="virtualKb">
<div id="keyboardLeft">
<div id="wasdKeys">
<button id="wKey">W</button>
<button id="aKey">A</button>
<button id="sKey">S</button>
<button id="dKey">D</button>
</div>
</div>
<div id="keyboardRight">
<div id="arrowKeys">
<button id="upKey">↑</button>
<button id="leftKey">←</button>
<button id="downKey">↓</button>
<button id="rightKey">→</button>
</div>
</div>
<div id="keyboardCenter">
<button id="eKey">E</button>
<button id="spaceBar">SPACE</button>
</div>
</div>`;
var el = document.createElement("div");
el.id = "virtualKbContainer";
el.innerHTML = html;
document.body.insertBefore(el, document.body.childNodes[0]);
// Создаем отдельные обработчики для каждой кнопки
function setupButton(id, keyName, keyCode, keyNumber) {
const btn = document.querySelector(id);
// Для мыши
btn.addEventListener("mousedown", () => pressKey('keydown', keyName, keyCode, keyNumber));
btn.addEventListener("mouseup", () => pressKey('keyup', keyName, keyCode, keyNumber));
btn.addEventListener("mouseleave", () => pressKey('keyup', keyName, keyCode, keyNumber));
// Для тач-устройств
btn.addEventListener("touchstart", (e) => {
e.preventDefault();
pressKey('keydown', keyName, keyCode, keyNumber);
});
btn.addEventListener("touchend", (e) => {
e.preventDefault();
pressKey('keyup', keyName, keyCode, keyNumber);
});
}
// Настраиваем все кнопки
setupButton("#upKey", "ArrowUp", "ArrowUp", 38);
setupButton("#leftKey", "ArrowLeft", "ArrowLeft", 37);
setupButton("#downKey", "ArrowDown", "ArrowDown", 40);
setupButton("#rightKey", "ArrowRight", "ArrowRight", 39);
setupButton("#wKey", "w", "KeyW", 87);
setupButton("#aKey", "a", "KeyA", 65);
setupButton("#sKey", "s", "KeyS", 83);
setupButton("#dKey", "d", "KeyD", 68);
setupButton("#spaceBar", " ", "Space", 32);
setupButton("#eKey", "e", "KeyE", 69);
setupButton("#esc-btn", "Escape", "Escape", 27);
}
// Функция для полноэкранного режима
document.getElementById('fullscreen-btn').addEventListener('click', function() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen().catch(err => {
console.error(`Error attempting to enable fullscreen: ${err.message}`);
});
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
});
addKeyboard();
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PORT 8080
#define BUFFER_SIZE 1024
#define ROOT_DIR "static"
void handle_request(int client_socket) {
char buffer[BUFFER_SIZE];
char path[BUFFER_SIZE];
char response_header[BUFFER_SIZE];
char full_path[BUFFER_SIZE 2];
struct stat file_stat;
int file_fd, bytes_read;
// Читаем запрос
read(client_socket, buffer, BUFFER_SIZE);
// Парсим путь из запроса (очень упрощённо)
sscanf(buffer, "GET %s HTTP/1.1", path);
// Обработка корневого пути
if (strcmp(path, "/") == 0) {
strcpy(path, "/index.html");
}
// Формируем полный путь к файлу
snprintf(full_path, sizeof(full_path), "%s%s", ROOT_DIR, path);
// Проверяем существование файла
if (stat(full_path, &file_stat) < 0 || S_ISDIR(file_stat.st_mode)) {
// Файл не найден - 404
char not_found = "HTTP/1.1 404 Not Found\r\n\r\n<html><body><h1>404 Not Found</h1></body></html>";
write(client_socket, not_found, strlen(not_found));
return;
}
// Открываем файл
file_fd = open(full_path, O_RDONLY);
if (file_fd < 0) {
perror("open");
return;
}
// Определяем Content-Type (очень упрощённо)
char content_type = "text/plain";
if (strstr(path, ".html")) content_type = "text/html";
else if (strstr(path, ".css")) content_type = "text/css";
else if (strstr(path, ".js")) content_type = "application/javascript";
else if (strstr(path, ".png")) content_type = "image/png";
else if (strstr(path, ".jpg") || strstr(path, ".jpeg")) content_type = "image/jpeg";
// Формируем заголовок ответа
snprintf(response_header, sizeof(response_header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %ld\r\n"
"Connection: close\r\n\r\n",
content_type, file_stat.st_size);
// Отправляем заголовок
write(client_socket, response_header, strlen(response_header));
// Отправляем содержимое файла
while ((bytes_read = read(file_fd, buffer, BUFFER_SIZE)) > 0) {
write(client_socket, buffer, bytes_read);
}
close(file_fd);
}
int main() {
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
// Создаём сокет
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
perror("socket");
exit(1);
}
// Настраиваем адрес сервера
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// Привязываем сокет к адресу
if (bind(server_socket, (struct sockaddr )&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
exit(1);
}
// Начинаем слушать соединения
if (listen(server_socket, 5) < 0) {
perror("listen");
exit(1);
}
printf("Server running on http://localhost:%d\n", PORT);
// Основной цикл сервера
while (1) {
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket < 0) {
perror("accept");
continue;
}
printf("Client connected: %s:%d\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
handle_request(client_socket);
close(client_socket);
}
close(server_socket);
return 0;
}
