Created
August 16, 2020 19:55
-
-
Save athas/93239da2c3bcae834a4895e4db557900 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <assert.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <arpa/inet.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <math.h> | |
#include <unistd.h> | |
#define MAX_PIXELS 140 | |
const int pixellength = 4; | |
struct sender { | |
int sockfd; | |
struct sockaddr_in server; | |
int n; | |
int capacity; | |
unsigned char *data; | |
}; | |
void flush(struct sender *s) { | |
char packet[1122]; | |
packet[0] = 4; // Version. | |
packet[1] = 0; // No alpha. | |
int offset = 0; | |
while (s->n > 0) { | |
int to_send = s->n/pixellength; | |
if (to_send > MAX_PIXELS) { | |
to_send = MAX_PIXELS; | |
} | |
ssize_t packet_size = 2+to_send*pixellength; | |
memcpy(packet+2, s->data+offset, to_send*pixellength); | |
if (sendto(s->sockfd, &packet, packet_size, 0, | |
(const struct sockaddr*)&s->server, sizeof(s->server)) != packet_size) { | |
abort(); | |
} | |
offset += to_send*pixellength; | |
s->n -= to_send*pixellength; | |
} | |
} | |
// Column major. | |
void pix(struct sender* s, uint16_t x, uint16_t y, uint32_t rgb32) { | |
if (s->n + pixellength > s->capacity) { | |
s->capacity = s->capacity * 2 + pixellength; | |
s->data = realloc(s->data, s->capacity); | |
} | |
uint8_t r = ((((rgb32>>16)&0xFF)/256.0)*8); | |
uint8_t g = ((((rgb32>>8)&0xFF)/256.0)*8); | |
uint8_t b = ((((rgb32>>0)&0xFF)/256.0)*4); | |
uint8_t rgb8 = (r << 5) | (g << 2) | b; | |
s->data[s->n++] = x; | |
s->data[s->n++] = ((x>>4)&0xf0) | (y&0xF); | |
s->data[s->n++] = y>>4; | |
s->data[s->n++] = rgb8; | |
if (s->n == MAX_PIXELS*pixellength) { | |
flush(s); | |
} | |
} | |
int32_t lerp(uint32_t rgb_x, uint32_t rgb_y, float t) { | |
float r_x = (rgb_x>>16)/256.0; | |
float g_x = ((rgb_x>>8)&0xFF)/256.0; | |
float b_x = (rgb_x&0xFF)/256.0; | |
float r_y = (rgb_y>>16)/256.0; | |
float g_y = ((rgb_y>>8)&0xFF)/256.0; | |
float b_y = (rgb_y&0xFF)/256.0; | |
int32_t r = (r_x + t*(r_y-r_x))*255; | |
int32_t g = (g_x + t*(g_y-g_x))*255; | |
int32_t b = (b_x + t*(b_y-b_x))*255; | |
return (r << 16) | (g << 8) | b; | |
} | |
int rate = 200; | |
void rect(struct sender* s, | |
uint16_t x, uint16_t y, | |
uint16_t w, uint16_t h, | |
uint32_t rgb) { | |
for (int i = 0; i < w; i++) { | |
for (int j = 0; j < h; j++) { | |
pix(s, x+i, y+j, rgb); | |
} | |
} | |
} | |
int in_circle(int i, int j, int x, int y, int r) { | |
return (x-i)*(x-i) + (y-j)*(y-j) <= r*r; | |
} | |
void circle(struct sender* s, uint16_t x, uint16_t y, | |
uint16_t r, uint32_t rgb) { | |
for (int i = x-r; i < x+r; i++) { | |
for (int j = y-r; j < y+r; j++) { | |
if (in_circle(i, j, x, y, r)) { | |
pix(s, i, j, rgb); | |
} | |
} | |
} | |
} | |
void ring(struct sender* s, uint16_t x, uint16_t y, | |
uint16_t r_outer, uint16_t r_inner, | |
uint32_t rgb) { | |
for (int i = x-r_outer; i < x+r_outer; i++) { | |
for (int j = y-r_outer; j < y+r_outer; j++) { | |
if (in_circle(i, j, x, y, r_outer) && | |
!in_circle(i, j, x, y, r_inner)) { | |
pix(s, i, j, rgb); | |
} | |
} | |
} | |
} | |
void movecircle(struct sender* s, | |
uint16_t old_x, uint16_t old_y, | |
uint16_t x, uint16_t y, | |
uint16_t r, | |
uint32_t bg, | |
uint32_t rgb0, uint32_t rgb1) { | |
for (int i = old_x-r; i < old_x+r; i++) { | |
for (int j = old_y-r; j < old_y+r; j++) { | |
if (in_circle(i, j, old_x, old_y, r) && | |
!in_circle(i, j, x, y, r)) { | |
pix(s, i, j, bg); | |
} | |
} | |
} | |
flush(s); | |
usleep(1000000/rate); | |
for (int i = x-r; i < x+r; i++) { | |
for (int j = y-r; j < y+r; j++) { | |
if (in_circle(i, j, x, y, r)) { | |
float t = sqrt(pow(i-x,2)+pow(j-y,2))/r; | |
pix(s, i, j, lerp(rgb0, rgb1, t)); | |
} | |
} | |
} | |
} | |
void clearcircle(struct sender* s, | |
uint16_t old_x, uint16_t old_y, | |
uint16_t x, uint16_t y, | |
uint16_t r, | |
uint32_t bg) { | |
for (int i = old_x-r; i < old_x+r; i++) { | |
for (int j = old_y-r; j < old_y+r; j++) { | |
if (in_circle(i, j, old_x, old_y, r) && | |
!in_circle(i, j, x, y, r)) { | |
pix(s, i, j, bg); | |
} | |
} | |
} | |
} | |
void pacman(struct sender *s, int x, int y, int r, | |
double t, double dir_angle, uint32_t rgb) { | |
double mouth_angle = fabs(sin(t))*1.5; | |
static double c = 3.14/2; | |
c += 0.001; | |
for (int i = x-r; i < x+r; i++) { | |
for (int j = y-r; j < y+r; j++) { | |
if (in_circle(i, j, x, y, r)) { | |
double angle = atan2((double)(j-y),(double)(i-x)) + M_PI/8 + dir_angle; | |
if (angle > 0 && angle < mouth_angle) { | |
pix(s, i, j, 0); | |
} else { | |
pix(s, i, j, rgb); | |
} | |
} | |
} | |
} | |
} | |
void scene(struct sender *s) { | |
srand(getpid()); | |
float mass = 0.002; | |
int r = 50; | |
int w = 1920; | |
int h = 1080; | |
float dy = 0; | |
float dx = 2; | |
float g = 9.82; | |
int x = rand()%w; | |
int y = rand()%h; | |
double time = 0; | |
uint32_t rgb = 0xFFFF00; | |
while (1) { | |
time += 0.1; | |
int old_x = x; | |
int old_y = y; | |
dy += g * mass; | |
y += dy; | |
x += dx; | |
if (y >= h-r) { | |
y = h-r; | |
dy = -dy; | |
} | |
if (y < r) { | |
y = r; | |
dy = -dy; | |
} | |
if (x >= w-r) { | |
x = w-r; | |
dx = -dx; | |
} | |
if (x <= r) { | |
x = r; | |
dx = -dx; | |
} | |
clearcircle(s, old_x, old_y, x, y, r, 0); | |
//usleep(1000000/rate); | |
double len = sqrt(dy*dy+dx*dx); | |
double dir_x = dx/len; | |
double dir_y = dy/len; | |
double dir = -atan2(dir_y,dir_x); | |
pacman(s, x, y, r, time, dir, rgb); | |
// flush(s); | |
usleep(1000000/rate); | |
} | |
} | |
int main() { | |
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); | |
struct sockaddr_in server = { 0 }; | |
assert(sockfd >= 0); | |
server.sin_family = AF_INET; | |
server.sin_addr.s_addr = inet_addr("100.65.0.2"); | |
server.sin_port = htons(5005); | |
struct sender s; | |
s.sockfd = sockfd; | |
s.server = server; | |
s.n = 0; | |
s.capacity = 0; | |
s.data = NULL; | |
scene(&s); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment