Skip to content

Instantly share code, notes, and snippets.

@athas
Created August 16, 2020 19:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save athas/93239da2c3bcae834a4895e4db557900 to your computer and use it in GitHub Desktop.
Save athas/93239da2c3bcae834a4895e4db557900 to your computer and use it in GitHub Desktop.
#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