Compare commits

...

3 Commits

Author SHA1 Message Date
bbed68cff2
C: check-root-user.c 2024-05-16 20:40:00 +03:00
60ba2c59e7
MicroPython stuff 2024-05-16 20:38:19 +03:00
a8e26be242
update V game 2024-05-11 21:12:26 +03:00
35 changed files with 737 additions and 126 deletions

5
code/C/.clang-format Normal file
View File

@ -0,0 +1,5 @@
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 2
ColumnLimit: 132
SortIncludes: Never

View File

@ -0,0 +1,18 @@
/**
* https://man.openbsd.org/getuid
*/
#include <unistd.h>
#include <stdio.h>
void main(int argc, char const *argv[]) {
uid_t user = getuid();
uid_t privs = geteuid();
printf("User: %u\n", user);
printf("Privs: %u\n", privs);
puts("::");
char *login = getlogin();
printf("%s\n", login);
}

View File

@ -3,10 +3,8 @@ atomic_bool running = true;
#define PORT 8000
#define PREFIX "/api"
int callback_default(const struct _u_request *request,
struct _u_response *response, void *user_data);
int callback_all_test_foo(const struct _u_request *request,
struct _u_response *response, void *user_data);
int callback_default(const struct _u_request *request, struct _u_response *response, void *user_data);
int callback_all_test_foo(const struct _u_request *request, struct _u_response *response, void *user_data);
void *thread_server(void *vargp) {
int ret;
@ -18,10 +16,8 @@ void *thread_server(void *vargp) {
instance.max_post_body_size = 1024;
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/param/:name", 0,
&callback_all_test_foo, "user data 1");
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/param/:name", 0,
&callback_all_test_foo, "user data 2");
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/param/:name", 0, &callback_all_test_foo, "user data 1");
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/param/:name", 0, &callback_all_test_foo, "user data 2");
ulfius_set_default_endpoint(&instance, &callback_default, NULL);
@ -41,18 +37,15 @@ void *thread_server(void *vargp) {
ulfius_clean_instance(&instance);
}
int callback_default(const struct _u_request *request,
struct _u_response *response, void *user_data) {
int callback_default(const struct _u_request *request, struct _u_response *response, void *user_data) {
(void)(request);
(void)(user_data);
ulfius_set_string_body_response(response, 404,
"Page not found, do what you want");
ulfius_set_string_body_response(response, 404, "Page not found, do what you want");
return U_CALLBACK_CONTINUE;
}
int callback_all_test_foo(const struct _u_request *request,
struct _u_response *response, void *user_data) {
int callback_all_test_foo(const struct _u_request *request, struct _u_response *response, void *user_data) {
// url_params = request->map_url
// post_params = request->map_post_body

View File

@ -2,128 +2,125 @@
#include "webui.h"
void my_function_string(webui_event_t* e) {
void my_function_string(webui_event_t *e) {
// JavaScript:
// webui_fn('MyID_One', 'Hello');
// JavaScript:
// webui_fn('MyID_One', 'Hello');
const char* str = webui_get_string(e);
printf("my_function_string: %s\n", str); // Hello
const char *str = webui_get_string(e);
printf("my_function_string: %s\n", str); // Hello
// Need Multiple Arguments?
//
// WebUI support only one argument. To get multiple arguments
// you can send a JSON string from JavaScript then decode it.
// Example:
//
// my_json = my_json_decoder(str);
// foo = my_json[0];
// bar = my_json[1];
// Need Multiple Arguments?
//
// WebUI support only one argument. To get multiple arguments
// you can send a JSON string from JavaScript then decode it.
// Example:
//
// my_json = my_json_decoder(str);
// foo = my_json[0];
// bar = my_json[1];
}
void my_function_integer(webui_event_t* e) {
void my_function_integer(webui_event_t *e) {
// JavaScript:
// webui_fn('MyID_Two', 123456789);
// JavaScript:
// webui_fn('MyID_Two', 123456789);
long long number = webui_get_int(e);
printf("my_function_integer: %lld\n", number); // 123456789
long long number = webui_get_int(e);
printf("my_function_integer: %lld\n", number); // 123456789
}
void my_function_boolean(webui_event_t* e) {
void my_function_boolean(webui_event_t *e) {
// JavaScript:
// webui_fn('MyID_Three', true);
// JavaScript:
// webui_fn('MyID_Three', true);
bool status = webui_get_bool(e); // True
if(status)
printf("my_function_boolean: True\n");
else
printf("my_function_boolean: False\n");
bool status = webui_get_bool(e); // True
if (status)
printf("my_function_boolean: True\n");
else
printf("my_function_boolean: False\n");
}
void my_function_with_response(webui_event_t* e) {
void my_function_with_response(webui_event_t *e) {
// JavaScript:
// const result = webui_fn('MyID_Four', number);
// JavaScript:
// const result = webui_fn('MyID_Four', number);
long long number = webui_get_int(e);
number = number * 2;
printf("my_function_with_response: %lld\n", number);
long long number = webui_get_int(e);
number = number * 2;
printf("my_function_with_response: %lld\n", number);
// Send back the response to JavaScript
webui_return_int(e, number);
// Send back the response to JavaScript
webui_return_int(e, number);
}
int main() {
// HTML
const char* my_html =
"<html>"
" <head>"
" <title>Call C from JavaScript Example</title>"
" <style>"
" body {"
" color: white;"
" background: #0F2027;"
" text-align: center;"
" font-size: 16px;"
" font-family: sans-serif;"
" }"
" </style>"
" </head>"
" <body>"
" <h2>WebUI - Call C from JavaScript Example</h2>"
" <p>Call C function with argument (<em>See the logs in your terminal</em>)</p>"
" <br>"
" <button onclick=\"webui_fn('MyID_One', 'Hello');\">Call my_function_string()</button>"
" <br>"
" <br>"
" <button onclick=\"webui_fn('MyID_Two', 123456789);\">Call my_function_integer()</button>"
" <br>"
" <br>"
" <button onclick=\"webui_fn('MyID_Three', true);\">Call my_function_boolean()</button>"
" <br>"
" <br>"
" <p>Call C function and wait for the response</p>"
" <br>"
" <button onclick=\"MyJS();\">Call my_function_with_response()</button>"
" <br>"
" <br>"
" <input type=\"text\" id=\"MyInputID\" value=\"2\">"
" <script>"
" function MyJS() {"
" const MyInput = document.getElementById('MyInputID');"
" const number = MyInput.value;"
" webui_fn('MyID_Four', number).then((response) => {"
" MyInput.value = response;"
" });"
" }"
" </script>"
" <script src=\"/webui.js\"></script>"
" </body>"
"</html>";
// HTML
const char *my_html = "<html>"
" <head>"
" <title>Call C from JavaScript Example</title>"
" <style>"
" body {"
" color: white;"
" background: #0F2027;"
" text-align: center;"
" font-size: 16px;"
" font-family: sans-serif;"
" }"
" </style>"
" </head>"
" <body>"
" <h2>WebUI - Call C from JavaScript Example</h2>"
" <p>Call C function with argument (<em>See the logs in your terminal</em>)</p>"
" <br>"
" <button onclick=\"webui_fn('MyID_One', 'Hello');\">Call my_function_string()</button>"
" <br>"
" <br>"
" <button onclick=\"webui_fn('MyID_Two', 123456789);\">Call my_function_integer()</button>"
" <br>"
" <br>"
" <button onclick=\"webui_fn('MyID_Three', true);\">Call my_function_boolean()</button>"
" <br>"
" <br>"
" <p>Call C function and wait for the response</p>"
" <br>"
" <button onclick=\"MyJS();\">Call my_function_with_response()</button>"
" <br>"
" <br>"
" <input type=\"text\" id=\"MyInputID\" value=\"2\">"
" <script>"
" function MyJS() {"
" const MyInput = document.getElementById('MyInputID');"
" const number = MyInput.value;"
" webui_fn('MyID_Four', number).then((response) => {"
" MyInput.value = response;"
" });"
" }"
" </script>"
" <script src=\"/webui.js\"></script>"
" </body>"
"</html>";
// Create a window
size_t my_window = webui_new_window();
// Create a window
size_t my_window = webui_new_window();
// Bind HTML elements with C functions
webui_bind(my_window, "MyID_One", my_function_string);
webui_bind(my_window, "MyID_Two", my_function_integer);
webui_bind(my_window, "MyID_Three", my_function_boolean);
webui_bind(my_window, "MyID_Four", my_function_with_response);
// Bind HTML elements with C functions
webui_bind(my_window, "MyID_One", my_function_string);
webui_bind(my_window, "MyID_Two", my_function_integer);
webui_bind(my_window, "MyID_Three", my_function_boolean);
webui_bind(my_window, "MyID_Four", my_function_with_response);
// Show the window
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);
// Show the window
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);
// Wait until all windows get closed
webui_wait();
// Wait until all windows get closed
webui_wait();
return 0;
return 0;
}
#if defined(_MSC_VER)
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) {
return main();
}
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
#endif

2
code/MicroPython/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
microdot/
utemplate/

View File

@ -0,0 +1,37 @@
#
##
```shell
# ...
esptool.py --port /dev/ttyACM0 erase_flash
# ...
esptool.py --chip esp32s2 --port /dev/ttyACM0 write_flash -z 0x1000 ~/Downloads/LOLIN_S2_MINI-20240222-v1.22.2.bin
```
```shell
pip3 install rshell #
pip3 install mpremote #
```
### Выполнение кода
```shell
rshell --port /dev/ttyACM0 cat blink.py
```
```python
import machine
import time
led = machine.Pin(15, machine.Pin.OUT)
led.on()
time.sleep(1)
led.off()
time.sleep(1)
```
```shell
mpremote exec 'exec(open("blink.py").read())'
```

View File

@ -0,0 +1,9 @@
import machine
import time
led = machine.Pin(15, machine.Pin.OUT)
led.on()
time.sleep(1)
led.off()
time.sleep(1)

4
code/MicroPython/boot.py Normal file
View File

@ -0,0 +1,4 @@
"""
Скрипт, который выполняется при старте EPS32.
После него выполняется скрипт `main.py`.
"""

163
code/MicroPython/ftp.py Normal file
View File

@ -0,0 +1,163 @@
import socket
import network
import os
import _thread
DATA_PORT = 13333
ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ftpsocket.bind(socket.getaddrinfo("0.0.0.0", 21)[0][4])
datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4])
ftpsocket.listen(1)
datasocket.listen(1)
datasocket.settimeout(10)
dataclient = None
def send_list_data(cwd, dataclient):
for file in os.listdir(cwd):
stat = os.stat(get_absolute_path(cwd, file))
file_permissions = "drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--"
file_size = stat[6]
description = "{} 1 owner group {:>13} Jan 1 1980 {}\r\n".format(
file_permissions, file_size, file
)
dataclient.sendall(description)
def send_file_data(path, dataclient):
with open(path) as file:
chunk = file.read(128)
while len(chunk) > 0:
dataclient.sendall(chunk)
chunk = file.read(128)
def save_file_data(path, dataclient):
with open(path, "w") as file:
chunk = dataclient.read(128)
while len(chunk) > 0:
file.write(chunk)
chunk = dataclient.read(128)
def get_absolute_path(cwd, payload):
# if it doesn't start with / consider
# it a relative path
if not payload.startswith("/"):
payload = cwd + "/" + payload
# and don't leave any trailing /
return payload.rstrip("/")
def ftp():
try:
dataclient = None
while True:
cwd = "/"
cl, remote_addr = ftpsocket.accept()
cl.settimeout(300)
try:
print("FTP connection from:", remote_addr)
cl.sendall("220 Hello, this is the ESP8266.\r\n")
while True:
data = cl.readline().decode("utf-8").replace("\r\n", "")
if len(data) <= 0:
print("Client is dead")
break
command, payload = (data.split(" ") + [""])[:2]
command = command.upper()
print("Command={}, Payload={}".format(command, payload))
if command == "USER":
cl.sendall("230 Logged in.\r\n")
elif command == "SYST":
cl.sendall("215 ESP8266 MicroPython\r\n")
elif command == "SYST":
cl.sendall("502\r\n")
elif command == "PWD":
cl.sendall('257 "{}"\r\n'.format(cwd))
elif command == "CWD":
path = get_absolute_path(cwd, payload)
try:
files = os.listdir(path)
cwd = path
cl.sendall('250 Directory changed successfully\r\n')
except:
cl.sendall('550 Failed to change directory\r\n')
elif command == "EPSV":
cl.sendall('502\r\n')
elif command == "TYPE":
# probably should switch between binary and not
cl.sendall('200 Transfer mode set\r\n')
elif command == "SIZE":
path = get_absolute_path(cwd, payload)
try:
size = os.stat(path)[6]
cl.sendall('213 {}\r\n'.format(size))
except:
cl.sendall('550 Could not get file size\r\n')
elif command == "QUIT":
cl.sendall('221 Bye.\r\n')
elif command == "PASV":
addr = network.WLAN().ifconfig()[0]
cl.sendall(
'227 Entering Passive Mode ({},{},{}).\r\n'.format(
addr.replace('.', ','), DATA_PORT >> 8, DATA_PORT % 256
)
)
dataclient, data_addr = datasocket.accept()
print("FTP Data connection from:", data_addr)
elif command == "LIST":
try:
send_list_data(cwd, dataclient)
dataclient.close()
cl.sendall("150 Here comes the directory listing.\r\n")
cl.sendall("226 Listed.\r\n")
except:
cl.sendall('550 Failed to list directory\r\n')
finally:
dataclient.close()
elif command == "RETR":
try:
send_file_data(get_absolute_path(cwd, payload), dataclient)
dataclient.close()
cl.sendall("150 Opening data connection.\r\n")
cl.sendall("226 Transfer complete.\r\n")
except:
cl.sendall('550 Failed to send file\r\n')
finally:
dataclient.close()
elif command == "STOR":
try:
cl.sendall("150 Ok to send data.\r\n")
save_file_data(get_absolute_path(cwd, payload), dataclient)
dataclient.close()
cl.sendall("226 Transfer complete.\r\n")
except:
cl.sendall('550 Failed to send file\r\n')
finally:
dataclient.close()
else:
cl.sendall("502 Unsupported command.\r\n")
print("Unsupported command {} with payload {}".format(command, payload))
finally:
cl.close()
finally:
datasocket.close()
ftpsocket.close()
if dataclient is not None:
dataclient.close()
_thread.start_new_thread(ftp, ())

View File

@ -0,0 +1,13 @@
"""
Скрипт, который возвращает MAC адрес
https://git.a2s.su/iiiypuk/snipplets.dev/src/branch/master/code/MicroPython
Update: May 14 2024
"""
import network
import ubinascii
mac = ubinascii.hexlify(network.WLAN().config('mac'), ':').decode()
print(mac)

79
code/MicroPython/http.py Normal file
View File

@ -0,0 +1,79 @@
import machine
import time
import gc
from microdot import Microdot, send_file, Request, Response
from microdot.utemplate import Template
led = machine.Pin(15, machine.Pin.OUT)
app = Microdot()
Response.default_content_type = 'text/html'
Request.max_content_length = 1024 * 1024
def cmd_parse(method, args):
if method == 'GET':
if 'cmd' in args:
cmd = args['cmd']
if 'reboot' == cmd:
for x in range(2):
led.on()
time.sleep_ms(200)
led.off()
time.sleep_ms(200)
machine.reset()
if 'ftp' == cmd:
exec(open('ftp.py').read())
@app.route('/static/<path:path>')
async def static(request, path):
if '..' in path:
# directory traversal is not allowed
return 'Not found', 404
return send_file('static/' + path)
@app.get('/file')
async def file(request):
return send_file('templates/upload.html')
@app.post('/upload')
async def upload(request):
filename = request.headers['Content-Disposition'].split('filename=')[1].strip('"')
size = int(request.headers['Content-Length'])
filename = filename.replace('/', '_')
with open('/' + filename, 'wb') as f:
while size > 0:
chunk = await request.stream.read(min(size, 1024))
f.write(chunk)
size -= len(chunk)
print('Successfully saved file: ' + filename)
return ''
@app.route('/')
async def index(request):
# print(request.args, request.path, request.method, sep='\n')
# print(request.url, request.query_string, request.url_args, sep='\n')
print(request.args)
cmd_parse(request.method, request.args)
ram_f = gc.mem_free()
ram_a = gc.mem_alloc()
ram_t = ram_a + ram_f
return Template('index.html').render(ram_free=int(ram_f / 1024), ram_total=int(ram_t / 1024))
print('HTTP server started')
app.run(port=80)

17
code/MicroPython/main.py Normal file
View File

@ -0,0 +1,17 @@
"""
Скрипт, который выполняется при старте EPS32.
После выполнения скрипта `boot.py`.
"""
import time
import network_ap
import network_sta
# Connecting to Wifi
wifi_connect = network_sta.connect('Keenetic-8647', 'sFJZi7U51')
if wifi_connect == False:
wifi_connect = network_ap.connect(essid='SkyNet', clients=2)
# If WiFi connected run HTTP server
if wifi_connect == True:
exec(open('http.py').read())

View File

@ -0,0 +1,21 @@
import time
import network
def connect(essid='ESP', clients=3) -> bool:
print('Starting AP: {0}...'.format(essid))
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=essid)
ap.config(max_clients=clients)
time.sleep(3)
if ap.isconnected():
print('AP "{0}" started'.format(essid))
return True
else:
print('Starting AP failed!')
return False

View File

@ -0,0 +1,38 @@
import time
import network
def connect(ssid: str, password: str) -> bool:
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.config(reconnects=2)
if not wlan.isconnected():
print('Scanning networks...')
wlan.scan()
print('Connecting to {0}...'.format(ssid))
# try:
wlan.connect(ssid, password)
while not wlan.isconnected():
status = wlan.status()
if status in (network.STAT_IDLE, network.STAT_WRONG_PASSWORD, network.STAT_NO_AP_FOUND):
print('\nConnection to "{0}" failed!'.format(ssid))
wlan.active(False)
return False
print('.', end='')
time.sleep(0.1)
print('\nConnection success!')
ifconfig = wlan.ifconfig()
print('IP: {0}'.format(ifconfig[0]))
return True
else:
print('Already connected!')
ifconfig = wlan.ifconfig()
print('IP: {0}'.format(ifconfig[0]))
return True

View File

@ -0,0 +1,3 @@
[tool.black]
skip-string-normalization = true
line-length = 100

View File

@ -0,0 +1,13 @@
import os
print('Listing filesystem...')
print(os.listdir(), '\n')
print('Write data...')
with open('data.txt', 'w') as f:
count = f.write('ololo\n')
print('Write', count, 'bytes')
print('Read data...')
with open('data.txt', 'r') as f:
print('Data:', f.read())

View File

@ -0,0 +1,3 @@
body {
background-color: #ccc;
}

View File

@ -0,0 +1,18 @@
{% args ram_free, ram_total %}
<!doctype html>
<html>
<head>
<title>S2F Terminal</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="/static/styles.css" rel="stylesheet">
</head>
<body>
<h1>by Alexander Popov</h1>
<p>Free RAM: {{ ram_free }} of {{ ram_total }}</p>
<div>
<a href="/?cmd=ftp">Поднять FTP сервер</a><br>
<a href="/?cmd=reboot">Перезапустить</a><br>
</div>
</body>
</html>

View File

@ -0,0 +1,23 @@
# Autogenerated file
def render(ram_free, ram_total):
yield """<!doctype html>
<html>
<head>
<title>S2F Terminal</title>
<meta charset=\"utf-8\">
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">
<link href=\"/static/styles.css\" rel=\"stylesheet\">
</head>
<body>
<h1>by Alexander Popov</h1>
<p>Free RAM: """
yield str(ram_free)
yield """ of """
yield str(ram_total)
yield """</p>
<div>
<a href=\"/?cmd=ftp\">Поднять FTP сервер</a><br>
<a href=\"/?cmd=reboot\">Перезапустить</a><br>
</div>
</body>
</html>"""

View File

@ -0,0 +1,35 @@
<!doctype html>
<html>
<head>
<title>Microdot Upload Example</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Microdot Upload Example</h1>
<form id="form">
<input type="file" id="file" name="file" />
<input type="submit" value="Upload" />
</form>
<script>
async function upload(ev) {
ev.preventDefault();
const file = document.getElementById('file').files[0];
if (!file) {
return;
}
await fetch('/upload', {
method: 'POST',
body: file,
headers: {
'Content-Type': 'application/octet-stream',
'Content-Disposition': `attachment; filename="${file.name}"`,
},
}).then(res => {
console.log('Upload accepted');
window.location.href = '/';
});
}
document.getElementById('form').addEventListener('submit', upload);
</script>
</body>
</html>

View File

View File

@ -1,4 +0,0 @@
* draw rect
* draw text
* draw image
* key event

1
projects/V/Game/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Game

82
projects/V/Game/README.md Normal file
View File

@ -0,0 +1,82 @@
* draw rect
* draw text
* draw image
* key event
## Build
### Linux
`...`
### Android
**Подготовка Android окружения**.
Необходимо выполнить следующие шаги:
1. Установка модуля `vab` для **V**
2. Установка **Android NDK**
3. Установка **android-tools**
4. Получение идентификатора устройства для деплоя
**Установка модуля `vab` для V**
```sh
v install vab
# Installed `vab` in ~/.vmodules/vab .
vab install "platforms;android-33" # Silent output... wait!
```
**Получение идентификатора устройства**
```sh
adb devices -l
```
https://developer.android.com/ndk
https://dl.google.com/android/repository/android-ndk-r26d-linux.zip
https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
Сборка `debug` пакета.
```sh
ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d"
VAB_FLAGS="-v 3 --name 'V App' --api 33 --build-tools 29.0.0" ~/.vmodules/vab/vab .
~/.vmodules/vab/vab --device ca4fcde6 run /home/user/Develop/snipplets.dev/projects/V/Game/v_app.apk
```
Сборка `release` пакета:
```sh
# Генерация sign.keystore
keytool -genkey -v -keystore sign.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
```
```sh
KEYSTORE_PASSWORD="Mix9BEAH" \
KEYSTORE_ALIAS_PASSWORD="Mix9BEAH" \
VAB_FLAGS="-v 3 --name 'V App' --api 33 --build-tools 29.0.0" \
~/.vmodules/vab/vab -prod --name "V App" --package-id "me.a2s.example" --icon ./assets/vlang.png --version-code 1 \
--keystore ./sign.keystore --keystore-alias "alias_name" .
```
### HTML (WASM)
Guide: https://github.com/vlang/v/tree/master/examples/2048#compiling-to-wasm
## OTHER
```sh
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android .
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android -nocache -cc clang .
ANDROID_SDK_ROOT="/home/user/.android/sdk/cmdline-tools/33" ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d" ANDROID_PACKAGE_NAME="test app" ANDROID_PACKAGE_ID="me.a2s.example" VAB_FLAGS="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 26.0.2" /home/user/.vmodules/vab/vab .
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17 /home/user/.local/bin/vlang/v -os android -nocache -cc clang -DSOKOL_GLES3 -dump-modules "/tmp/vab/v/v.modules" -dump-c-flags "/tmp/vab/v/v.cflags" .
VCROSS_COMPILER_NAME=/home/user/.android/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang /home/user/.local/bin/vlang/v -os android android.v
```

BIN
projects/V/Game/android Executable file

Binary file not shown.

View File

@ -0,0 +1,3 @@
fn main() {
print('Loading... ')
}

View File

@ -0,0 +1 @@
../../../../assets/monogram-extended.ttf

View File

@ -0,0 +1 @@
../../../../assets/tiled_bg.png

View File

@ -0,0 +1 @@
../../../../assets/languages/vlang.png

30
projects/V/Game/build.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
# Обновление PATH
PATH="~/.local/bin/vlang:~/.vmodules/vab:$PATH"
# Настройки Android
export ANDROID_SDK_ROOT="/home/user/.android/sdk/cmdline-tools/33"
export ANDROID_NDK_ROOT="/home/user/.android/android-ndk-r26d"
ANDROID_DEVICE_ID="ca4fcde6"
ANDROID_PACKAGE_NAME="test app"
ANDROID_PACKAGE_ID="me.a2s.example"
VAB_FLAGS_DEBUG="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 29.0.0"
VAB_FLAGS_RELEASE="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 29.0.0 --icon ./assets/vlang.png --version-code 1 --keystore ./sign.keystore --keystore-alias \"alias_name\""
debug() {
VAB_FLAGS=$VAB_FLAGS_DEBUG vab $(pwd)
# vab --device $ANDROID_DEVICE_ID run ./v_app.apk
}
release() {
echo "WIP"
}
test() {
VAB_FLAGS="-v 3 --name $ANDROID_PACKAGE_NAME --package-id $ANDROID_PACKAGE_ID --api 33 --build-tools 26.0.2" vab android.v
}
test

View File

@ -12,7 +12,7 @@ fn (game &Game) draw() {
gx.white, 'right', 'top', true)
// draw image
game.gg.draw_image(0, game.gg.window_size().height - game.player.image.height, game.player.image.width,
game.gg.draw_image(game.player.pos_x, game.player.pos_y, game.player.image.width,
game.player.image.height, game.player.image)
game.gg.end()

View File

@ -3,10 +3,8 @@ import gg
import gx
import sokol.sapp
const (
win_width = 512
win_height = 512
)
const win_width = 768
const win_height = 768
struct Game {
mut:
@ -39,7 +37,7 @@ fn main() {
print('Loading... ')
mut game := &Game{}
mut font_path := os.resource_abs_path(os.join_path('..', '..', '.assets', 'monogram-extended.ttf'))
mut font_path := os.resource_abs_path(os.join_path('assets', 'monogram-extended.ttf'))
game.gg = gg.new_context(
bg_color: gx.hex(0x2A2A3AFF)
@ -55,8 +53,8 @@ fn main() {
)
game.player = &Player{
pos_x: 10
pos_y: 10
pos_x: 50
pos_y: 50
lives: 3
}
@ -65,10 +63,10 @@ fn main() {
pos_y: 0
}
game.bg_texture.image = game.gg.create_image(os.resource_abs_path(os.join_path('..',
'..', '.assets', 'fondo para itchio.png'))) or { panic(err) }
game.player.image = game.gg.create_image(os.resource_abs_path(os.join_path('..', '..',
'.assets', 'v-logo.png'))) or { panic(err) }
game.bg_texture.image = game.gg.create_image(os.resource_abs_path(os.join_path('assets',
'tiled_bg.png'))) or { panic(err) }
game.player.image = game.gg.create_image(os.resource_abs_path(os.join_path('assets',
'vlang.png'))) or { panic(err) }
println('OK!\n')
println('High DPI: ${gg.high_dpi()}')

7
projects/V/Game/v.mod Normal file
View File

@ -0,0 +1,7 @@
Module {
name: 'game',
description: '...',
version: '0.0.0',
repo_url: '...',
dependencies: []
}