Emptying repo for new version of site

This commit is contained in:
Warwick 2024-05-10 13:53:43 +01:00
parent 8d26174bd3
commit 4cba46e398
56 changed files with 0 additions and 9469 deletions

View file

@ -1,13 +0,0 @@
entrypoint=index.html
postbuild: build
node postbuild.js
build: node_modules
npx parcel build ${entrypoint}
node_modules:
npm install
clean:
git clean -xdf

View file

@ -1,5 +0,0 @@
<html>
<body>
<script type='module' src="./src/index.jsx"></script>
</body>
</html>

8066
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,42 +0,0 @@
{
"name": "portfolio-site",
"version": "1.0.0",
"description": "Portfolio Site",
"scripts": {
"start": "rm -v dist/* && node postbuild.js && parcel index.html",
"build": "rm -rv dist && parcel build index.html && exec node postbuild.js"
},
"browserslist": [
"defaults",
"not IE 11",
"maintained node versions"
],
"author": "",
"license": "BSD-2-Clause",
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/plugin-transform-react-jsx": "^7.12.5",
"cssnano": "^5.1.0",
"parcel": "^2.7.0",
"typescript": "^4.0.5"
},
"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.11.2",
"@types/react": "^16.9.56",
"fontsource-roboto": "^3.0.3",
"hls.js": "^1.1.5",
"preact": "^10.5.5",
"preact-async-route": "^2.2.1",
"preact-router": "^3.2.1",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"video.js": "^7.10.2"
},
"skipLibCheck": true,
"alias": {
"react": "preact/compat",
"react-dom/test-utils": "preact/test-utils",
"react-dom": "preact/compat"
}
}

View file

@ -1,57 +0,0 @@
const Path = require("path");
const fs = require("fs");
fs.copyFile("./static/video/background_video/index0.ts",
"./dist/index0.ts", (err) => {
if (err) {
return
console.error("Video segments were not copied! \n",
err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index1.ts", "./dist/index1.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index2.ts", "./dist/index2.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index3.ts", "./dist/index3.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index4.ts", "./dist/index4.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index5.ts", "./dist/index5.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});
fs.copyFile("./static/video/background_video/index6.ts", "./dist/index6.ts", (err) => {
if (err) {
return console.error("Video segments were not copied! \n", err);
} else {
return console.error("Video segments successfully copied! \n");
}
});

View file

@ -1,28 +0,0 @@
import { h, render, Component } from "preact";
import {
Container,
Card,
CardContent,
Typography,
} from "@material-ui/core";
class LostPage extends Component {
render() {
return (
<span>
<Container maxWidth="sm" >
<Card>
<CardContent>
<Typography variant="h1"> Error 404</Typography>
<Typography variant="body1">
There is no content here...
</Typography>
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default LostPage;

View file

@ -1,19 +0,0 @@
import { h, render, Component } from "preact";
const background = new URL("../static/javascript/background.js", import.meta.url);
class Background extends Component {
componentDidMount() {
const script = document.createElement("script");
script.src = background;
script.async = true;
document.body.appendChild(script);
}
render() {
return (
<span>
</span>
);
}
}
export default Background;

View file

@ -1,55 +0,0 @@
import { h, render, Component } from "preact";
import Header from "./Header";
import {
Container,
Card,
CardHeader,
CardContent,
Typography,
List,
ListItem,
ListItemText,
Link,
} from "@material-ui/core";
class Contact extends Component {
render() {
return (
<span>
<Header />
<Container maxWidth="md">
<p />
<Card>
<CardHeader title="Contact" />
<CardContent>
<ListItemText>
LinkedIn:{" "}
<Link
rel="noopener"
href="https://www.linkedin.com/in/warwick-new-96491a147/ "
>
https://www.linkedin.com/in/warwick-new-96491a147/
</Link>
</ListItemText>
<ListItemText>
Email:{" "}
<Link rel="noopener" href="mailto:warwick.l.e.new@gmail.com">
warwick.l.e.new@gmail.com
</Link>
</ListItemText>
<ListItemText>
Phone Number:{" "}
<Link rel="noopener" href="tel:07445728181">
07445 728 181
</Link>
</ListItemText>
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default Contact;

View file

@ -1,132 +0,0 @@
import { h, render, Component } from "preact";
import {
Grid,
Container,
Card,
CardHeader,
CardMedia,
CardActions,
CardContent,
Typography,
Button,
} from "@material-ui/core";
import Monq from "../static/images/Monq.jpg";
import Graphics from "../static/images/Graphics.png";
import NewGraphics from "../static/images/NewGraphics.png";
import Code from "../static/images/code.png";
class GameProjects extends Component {
constructor(props) {
super(props);
this.content = [
{
header: "Current Graphics Project",
subheader: `Personal Side Project - Programmer: C++, Opengl, SDL`,
image: NewGraphics,
imageAltText: "Graphics",
content: `I'm currently working on another graphics project as this is
the area of computing I want to get back to working in. I plan on
generating a cyberpunk city and implementing other features that you
may find in a game engine, such as including a physics engine for a
more complex character controller and an entity system so I can
implement vehicles and other methods of terrain traversal.`,
buttonText: "Read Blog",
buttonLink: "/graphics-blog",
newtab: false
},
{
header: "Current Low Level Networking Project",
subheader: `Personal Side Project - Programmer: C, Sockets and Protobuf`,
image: Code,
imageAltText: "Networking Code",
content: `I'm currently working on another low level project as
interested in learning plain C and low level networking. I plan on
creating a mud that can potentially be used in conjunction with my
graphics project to create a multiplayer experience.`,
buttonText: "Visit Repo",
buttonLink: "https://github.com/WarwickNew/urchin",
newtab: false
},
{
header: "Monq",
subheader: `D-tail Entertainment - Programmer: Unreal Engine 4, C++,
Blueprints`,
image: Monq,
imageAltText: "Monq",
content: `Monq was developed by an indie startup which I founded
alongside classmates from my university. It was developed in Unreal
Engine 4 using a mixture of C++ and blueprints. I predominantly worked
on the AI mechanics and puzzle implementation of the game, though due
to the nature of working in a small team I was able to contribute to
puzzle design and texture generation through shaders.`,
buttonText: "Learn More",
buttonLink: "/monq",
newtab: false
},
{
header: "University Graphics Project",
subheader: `Falmouth University (Bsc hons: Computing for Games) -
Programmer: C++,
Opengl, SDL`,
image: Graphics,
imageAltText: "Generated terrain",
content: `This is where I learned how to create a graphics engine from
scratch using OpenGL, and was the project which I enjoyed the most
during my bachelor's degree. Here I learned the basics of GLSL shaders
to achive flat face lighting, blending colours based on position and
generating meshes based on perlin noise. I even created a movement
system which keeps the camera a fixed distance above the noise value.
I especially enjoyed how deep I jumped into C++ to improve its memory
footprint returning to this project in my final year of university,
leaning more about pointers and memory management.`,
buttonText: "Learn More",
buttonLink: "/uni-graphics",
newtab: false
},
];
}
render = () => {
return (
<Container>
<p />
<Card>
<CardHeader title="Game Development Projects" />
</Card>
<p />
<Grid container spacing={3}>
{this.content.map((project) => {
return (
<Grid item xs="12" lg="6">
<Card>
<CardHeader
title={project.header}
subheader={project.subheader}
/>
<CardMedia
style={{ height: 0, paddingTop: "25%" }}
image={project.image}
title={project.imageAltText}
/>
<CardContent>
<Typography variant="body1">{project.content}</Typography>
</CardContent>
<CardActions>
<Button
target={project.newtab ? "_blank" : ""}
href={project.buttonLink}
color="primary"
>
{project.buttonText}
</Button>
</CardActions>
</Card>
</Grid>
);
})}
</Grid>
</Container>
);
};
}
export default GameProjects;

View file

@ -1,260 +0,0 @@
import { h, render, Component } from "preact";
import {
Grid,
Container,
Card,
CardHeader,
CardMedia,
CardActions,
CardContent,
Typography,
Button,
List,
ListItemIcon,
ListItem,
Link,
} from "@material-ui/core";
import ArrowRightIcon from '@material-ui/icons/ArrowRight';
import Header from "./Header";
import Blog1 from "../static/images/GraphicsBlog/blog1.png";
const Blog2 = new URL("../static/video/graphics_blog/blog2.webm", import.meta.url);
import Blog3 from "../static/images/GraphicsBlog/blog3.png";
import Blog4 from "../static/images/GraphicsBlog/blog4.png";
import Blog5 from "../static/images/GraphicsBlog/blog5.png";
import Blog6 from "../static/images/GraphicsBlog/blog6.png";
const Blog7 = new URL("../static/video/graphics_blog/blog7.mp4", import.meta.url);
const Blog8 = new URL("../static/video/graphics_blog/blog8.mp4", import.meta.url);
const Blog9 = new URL("../static/video/graphics_blog/blog9.mp4", import.meta.url);
const Blog10 = new URL("../static/video/graphics_blog/blog10.mp4", import.meta.url);
class GraphicsBlog extends Component {
constructor(props) {
super(props);
this.content = [
{
header: "SDL/OpenGL boilerplate",
subheader: "Note: this blog is a copy of a forum thread",
mediaType: "img",
image: Blog1,
imageAltText: "Textured square",
content: `Today I added textures to my game engine. Next up
refactoring... But then camera movement (Or strangely enough world
movement around the camera).`,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Camera Movement",
subheader: "Note: this blog is a copy of a forum thread",
mediaType: "video",
image: Blog2,
imageAltText: "Textured square with camera movement",
content: `The project is now officially 3D, with camera movement. Next
up is more complex meshes.`,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Multiple Meshes",
subheader: "Note: this blog is a copy of a forum thread",
mediaType: "img",
image: Blog3,
imageAltText: "2 textured squares",
content: `Now that I have a mesh class it's pretty easy to make multiple objects reusing textures and indices. Next, it's giving those meshes their own relative position rather than hard coding every position on every triangle point to move it 🙃.`,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Models with their own Model space.",
subheader: "Note: this blog is a copy of a forum thread",
mediaType: "img",
image: Blog4,
imageAltText: "3 Textured squares",
content: <span>Models now have their own position in world space and
can be made up of multiple meshes. They can also be moved
dynamically.<p /> I got 3 different directions to go now. 1) start
working on a lighting system which will teach me more about low level
shaders and their maths, 2) create a method of loading in models
exported from blender, 3) start messing about with creating and
rendering shapes with noise. <p /> Comment) lighting is fun <p />
Answer) Light is cool, but to get good lighting I'm gonna need to
start working with vertex normals and UVs and that's without shadows.
So maybe it'll actually be worth me importing models where I know
this stuff isn't broken first, and then messing about with lighting
on that. idk, we'll see how I feel once I optimise what I
have.</span>,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Loading models into the engine.",
subheader: "",
mediaType: "img",
image: Blog5,
imageAltText: "3 stages of model loading described in the description box",
content: "I decided I wanted something in my engine to test lighting on before I go further, I ran into a few problems along the way but here's the visual progression of things. The first image was me not sending the correct texture reference to the GPU followed by loading in the texture upside down, you know normal debugging stuff. It took me a few tries to get the textures loaded incorrectly as you can see but once I reverse-engineered some boilerplate example code for the order of execution when loading multiple textures the rest just fell into place.",
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Basic Lighting.",
subheader: "",
mediaType: "img",
image: Blog6,
imageAltText: "A graphical render of a coloured cube and a guitar backpack with a simple light.",
content: "Now I have a model loaded I've decided to focus on lighting for a bit. After implementing some simple diffuse lighting here I think I'm gonna go all in and jump straight to a PBR system.",
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Metalness",
subheader: "",
mediaType: "video",
image: Blog7,
imageAltText: "A render of light moving around a cube and a barrel",
content: <span>I've decided to go with the metalness, roughness, and AO version of PBR as the online documentation for its implementation appears far more accessible, special thanks to <Link component="span" rel="noopener" href="https://learnopengl.com/PBR/Theory" >LearnOpenGL.com</Link> In this video you can see a slightly wonky metalness implementation where the specular part of the algorithm appears to be inverted. I also expanded the material loading system to load in the Metalness.</span>,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Metalness and Roughness",
subheader: "",
mediaType: "video",
image: Blog8,
imageAltText: "A render of light moving around a cube and a barrel",
content: <span>It was almost too easy but thanks to my metalness implementation I've been able to easily extend the material system to load multiple additional textures into the shader. making implementing roughness as easy as plugging it into the algorithm I've implemented for metalness.</span>,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Full PBR",
subheader: "",
mediaType: "video",
image: Blog9,
imageAltText: "A render of light moving around a cube and a barrel",
content: <span>And here we have full PBR in the flesh. I think the only thing that's missing now is normal maps. I've also packed all the separate PBR textures into a single RMA texture, meaning that I only need to load one texture for the roughness, metalness and AO. Whilst I've got PBR working I think that for this project using a cube map with IBL to create realistic reflections will be overkill unless I really think environmental reflections are important for reflective surfaces like windows. But if I use a cube map for that situation, the effort will be better spent using one to mimic an interior instead.</span>,
buttonText: undefined,
buttonLink: undefined,
},
{
header: "Normal Maps",
subheader: "",
mediaType: "video",
image: Blog10,
imageAltText: "A render of light moving around a cube and a barrel",
content: <span>It&apos;s been great to have the opportunity to dive into a hard maths topic again as I haven't felt this challenged since my <Link href='/uni-graphics'>university graphics project</Link>. I can now say I have an intuitive understanding of linear trigonometry again. Especially after reimplementing normal maps fully in the geometry shader using the triangle primitives available in that part of the pipeline to calculate the tangent space in the GPU rather than doing so on the CPU like on <Link component="span" rel="noopener" href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping" >LearnOpenGL.com</Link>. If anyone needs an amazing refresher on linear algebra I can't recommend <Link component="span" rel="noopener" href="https://youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab">3Blue1Brown&apos;s series on the topic</Link> more. </span>,
buttonText: undefined,
buttonLink: undefined,
},
];
}
render = () => {
return (
<span>
<Header />
<Container>
<p />
<Card>
<CardHeader title="Graphics Blog" />
<CardContent>
<Typography variant="p" >
In this project, I am going to generate a cyberpunk cityscape with
an infinite level of verticality to give it a large sense of
scale. The project is written in C++ using SDL to manage
windows and OpenGL to render the meshes.
</Typography>
<List dense>
<Typography variant="p" >
To Do:
</Typography>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Run a marching square implementation to generate a mesh for a
chunk based on test data.
</ListItem>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Handle loading chunks asynchronously as the game runs.
</ListItem>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Add a noise algorithm to vary the cityscape marching square
generation. (Looking at &nbsp;
<Link
component="span"
rel="noopener"
href="https://github.com/Aubrrn/FastNoise2"
> FastNoise2 </Link>
)
</ListItem>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Create a mesh data library to make the marching square
algorithm generate something that looks like a city. (May
require a method of importing models)
</ListItem>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Design and create an interesting movement system for the
world created. (May need a physics engine like &nbsp;
<Link
component="span"
rel="noopener"
href="https://github.com/bulletphysics/bullet3"
> Bullet Engine </Link>
)
</ListItem>
<ListItem>
<ListItemIcon><ArrowRightIcon /></ListItemIcon>
Look into the potential implementation of mono-rails and
suspended trains as a stretch goal.
</ListItem>
</List>
</CardContent>
</Card>
<p />
<Grid container spacing={3}>
{this.content.reverse().map((project) => {
return (
<Grid item xs="12" lg="6">
<Card>
<CardHeader
title={project.header}
subheader={project.subheader}
/>
<CardMedia
component={project.mediaType}
image={project.image}
alt={project.imageAltText}
muted
loop
autoplay
controls
/>
<CardContent>
<Typography variant="body1" >
{project.content}
</Typography>
</CardContent>
<CardActions>
<Button
target="_blank"
href={project.buttonLink}
color="primary"
>
{project.buttonText}
</Button>
</CardActions>
</Card>
</Grid>
);
})}
</Grid>
</Container>
</span>
);
};
}
export default GraphicsBlog;

View file

@ -1,65 +0,0 @@
import { h, render, Component } from "preact";
import {
Container,
Card,
CardActions,
CardContent,
Typography,
Button,
} from "@material-ui/core";
const CV = new URL("../static/cv.pdf", import.meta.url);
import VideoPlayer from "./VideoPlayer.jsx";
class Greeting extends Component {
render() {
return (
<div>
<div
style={{
position: "absolute",
width: "100%",
left: "49%",
right: "49%",
top: "30%",
height: "60%",
objectFit: "cover",
transform: "translate(-49%,-50%)",
zIndex: "-1",
}}
>
<VideoPlayer />
</div>
<Container
maxWidth="sm"
style={{
zindex: "0",
}}
>
<p />
<Card>
<CardContent>
<Typography variant="h1">Welcome</Typography>
<Typography variant="body1">
Hi, My name is Warwick and I'm an Associate Lecturer in
Computing at the Games Academy in Falmouth University, with an
academeic background in Computing for Games and
Entrepreneurship. I'm currently looking for oppertunities which
would allow me to explore my interests whether thats graphics
programming and simulation, or developing and even deeper
understanding of linux based technologies.
</Typography>
</CardContent>
<CardActions>
<Button href={CV} color="secondary">
My Corriculum Vitae
</Button>
</CardActions>
</Card>
</Container>
</div>
);
}
}
export default Greeting;

View file

@ -1,74 +0,0 @@
import { h, render, Component } from "preact";
import {
AppBar,
Toolbar,
Container,
Typography,
Button,
Box,
Link,
} from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
const CV = new URL("../static/cv.pdf", import.meta.url);
class Header extends Component {
constructor(props) {
super(props);
this.styles = makeStyles({
toolbarButtons: {
marginLeft: "auto",
},
});
}
render() {
const classes = this.styles();
return (
<AppBar position="sticky">
<Toolbar>
<Link color="inherit" href="/">
<Typography variant='h5' component='h1' style={{ flex: 1 }}>
Warwick New
</Typography>
</Link>
<Box />
<span style={{ marginLeft: "auto" }} >
<Button
variant="text"
href="/graphics-blog"
style={{ color: "#f0ffd6" }}
>
Graphics Blog
</Button>
{" "}
<Button
variant="text"
href="/research"
style={{ color: "#f0ffd6" }}
>
Research Contributions
</Button>
{" "}
<Button
variant="text"
href={CV}
style={{ color: "#f0ffd6" }}
>
CV
</Button>
{" "}
<Button
variant="text"
href="/contact"
style={{ color: "#f0ffd6" }}
>
Contact Me
</Button>
</span>
</Toolbar>
</AppBar>
);
}
}
export default Header;

View file

@ -1,25 +0,0 @@
import { h, render, Component } from "preact";
import { Container } from "@material-ui/core";
import Header from "./Header";
import Greeting from "./Greeting";
import WebProjects from "./WebProjects";
import GameProjects from "./GameProjects";
class Home extends Component {
render() {
return (
<span>
<Header />
<Greeting />
<div style={{ "margin-top": "8em" }} />
<GameProjects />
<Container maxWidth="md">
<WebProjects />
</Container>
<p />
</span>
);
}
}
export default Home;

View file

@ -1,152 +0,0 @@
import { h, render, Component } from "preact";
import Header from "./Header";
import {
Button,
Container,
Card,
CardHeader,
CardContent,
Typography,
Grid,
Box
} from "@material-ui/core";
const tigerPicture = new URL("../static/images/MonqPage/TigerAI.png", import.meta.url);
const tigerDiagram = new URL("../static/images/MonqPage/TigerDiagram.png", import.meta.url);
const sandPicture = new URL("../static/images/MonqPage/Sand.png", import.meta.url);
const mirrorPicture = new URL("../static/images/MonqPage/MirrorReflection.png", import.meta.url);
class Monq extends Component {
render() {
return (
<span>
<Header />
<p />
<Container maxWidth="md">
<Card>
<CardHeader title="Monq" />
<CardContent>
<Typography variant="p">
This is my most complete game project. I made it in my second
year of university with some friends, and we were going to use
it to form a successful startup. I learned a lot about how a
multidisciplinary team works and tinkered with creating
frameworks in C++ with inheritance both to blueprints and
further C++ sub-classes, covering concepts such as all the AI
using unreal's tools, puzzle implementation, shader
implementation using noise and more. Most of the mechanics for
which I was responsible, used a variety of vector and
positional mathematics to implement.
</Typography>
<p />
<Typography variant="h5"> Project and Team </Typography>
<Grid container spacing={2}>
<Grid item sm={6} xs={12}>
<Typography variant="h6"> Programming: </Typography>
<Typography variant="p"> Warwick New, </Typography>
<Typography variant="p"> James Hellman </Typography>
<Typography variant="h6"> Designers: </Typography>
<Typography variant="p"> James Hellman, </Typography>
<Typography variant="p"> Nicholas Stankowski </Typography>
<Typography variant="h6"> Art: </Typography>
<Typography variant="p"> Harri Slee, </Typography>
<Typography variant="p"> Robert Adolfson </Typography>
<Typography variant="h6"> Music: </Typography>
<Typography variant="p"> Jason Read </Typography>
<Typography variant="h6"> Writing: </Typography>
<Typography variant="p"> Michael Wheatley </Typography>
<Typography variant="h6"> Animation: </Typography>
<Typography variant="p"> George Evans, </Typography>
<Typography variant="p"> Ross Everson </Typography>
</Grid>
<Grid item sm={6}>
<iframe
style={{ display: "block", margin: "auto", float: "right" }}
width="560" height="315"
src="https://www.youtube-nocookie.com/embed/fRSD64D0LUw"
title="YouTube video player" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media;
gyroscope; picture-in-picture" allowfullscreen>
</iframe>
</Grid>
</Grid>
<p />
<iframe
style={{ display: "block", margin: "0 auto" }}
src="https://itch.io/embed/131406" height="167" width="552"
frameborder="0">
<a
href="https://d-tail-entertainment.itch.io/monq">MONQ by
dtailent
</a>
</iframe>
<p />
<Typography variant="h5"> Stuff I worked on </Typography>
<Typography variant="h6"> Tiger AI </Typography>
<Grid container spacing={2}>
<Grid item sm={6} xs={12}>
Here I created an AI that guards an arena. The puzzle part
of this boss was based on trying to get the ai to get a
chain stuck on pillars left around the arena reducing the
range it could navigate. I did this by calculating the
distance between the previous attachment point and the next
and reducing the available navigatable circumference of the
tiger appropriately. Since this was my first more
complicated AI, I now know that It would have been far
easier to restrict the AI's movement through the use of a
more complex steering system rather than calculating where
the actor should target moving towards.
</Grid>
<Grid item sm={6}>
<Box
component="img"
alt="Image of Tiger AI"
src={tigerPicture}
style={{ width: "100%", "float": "right" }}
/>
</Grid>
</Grid>
<Box
component="img"
alt="Diagram of Tiger AI"
src={tigerDiagram}
style={{ width: "100%", "float": "right" }}
/>
<Typography variant="h6"> Mirror Reflections </Typography>
<Grid container spacing={2}>
<Grid item sm={6}>
<Box
component="img"
alt="Image of mirror reflection"
src={mirrorPicture}
style={{ width: "100%", "float": "left" }}
/>
</Grid>
<Grid item sm={6} xs={12}>
Here is an example of me simulating reflections in monq to
create a light bounce puzzle. Each mirror triggers the next
to recursively make light reflection beams. Here I had to
work out angles of reflection before creating a new cast to
attach a beam particle.
<p />
I also worked on the sand texture in this image mixing
various forms of noise to create the ripples based on
changes in topography.
</Grid>
</Grid>
<p />
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default Monq;

View file

@ -1,70 +0,0 @@
import { h, render, Component } from "preact";
import Header from "./Header";
import {
Container,
Card,
CardHeader,
CardContent,
Typography,
} from "@material-ui/core";
const rambleDemoWebm = new URL("../static/video/ramble_demo/ramble.webm", import.meta.url);
const rambleDemoMp4 = new URL("../static/video/ramble_demo/ramble.mp4", import.meta.url);
class Ramble extends Component {
render() {
return (
<span>
<Header />
<p />
<Container maxWidth="md">
<Card>
<CardHeader title="Ramble" />
<CardContent>
<Typography variant="p">
Ramble was a web project I created during my master's degree to
create a startup. In this project, I was the CTO and built a
website that allowed users to stream their podcasts live and
accept call-ins in a similar vein to talk shows! I learnt the
entire javascript web development stack from React to audio
streaming to DevOps in order to make it a reality.
</Typography>
<p />
<Typography variant="p">
It also had chatroom functionality with the ability to
re-stream to audiences much like other apps that came out in
the time since, such as Clubhouse.
</Typography>
<p />
<Typography variant="p">
During the project's lifespan of just under two years, I mostly
worked on creating the streaming functionality of the project
and managing how the project was designed to function behind
the hood when it was deployed. I learned a ton about how web
deployment works during this time allowing me to work on web
development modules in the Games Academy at Falmouth University
today.
</Typography>
<p />
<Typography variant="p">
Here's a demo of the project I took before we moved on.
</Typography>
<p />
<div>
<video controls loop muted autoPlay={true} style={{
width: "100%",
height: "auto",
objectFit: "cover",
}}>
<source src={rambleDemoMp4} type="video/mp4" />
<source src={rambleDemoWebm} type="video/webm" />
</video>
</div>
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default Ramble;

View file

@ -1,55 +0,0 @@
import { h, render, Component } from "preact";
import Header from "./Header";
import {
Container,
Card,
CardHeader,
CardContent,
Typography,
List,
ListItem,
ListItemText,
Link,
} from "@material-ui/core";
class Contact extends Component {
render() {
return (
<span>
<Header />
<Container maxWidth="md">
<p />
<Card>
<CardHeader title="Research Contributions" />
<CardContent>
<ListItemText>
An Exploratory Analysis of Student Experiences with Peer Evaluation in Group Game Development Projects:{" "}
<p>
<Link
rel="noopener"
href="https://dl.acm.org/doi/10.1145/3555009.3555021"
>
https://dl.acm.org/doi/10.1145/3555009.3555021
</Link>
</p>
</ListItemText>
<ListItemText>
Student Perspectives on the Purpose of Peer Evaluation During Group Game Development Projects:{" "}
<p>
<Link
rel="noopener"
href="https://dl.acm.org/doi/10.1145/3481282.3481294"
>
https://dl.acm.org/doi/10.1145/3481282.3481294
</Link>
</p>
</ListItemText>
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default Contact;

View file

@ -1,61 +0,0 @@
import { h, render, Component } from "preact";
import Header from "./Header";
import {
Button,
Container,
Card,
CardHeader,
CardContent,
Typography,
} from "@material-ui/core";
const graphicsDemoMp4 = new URL("../static/video/uni_graphics_demo/uni-graphics.mp4", import.meta.url);
const graphicsDemoBuild = new URL("../static/builds/UniGraphics-Win64.zip", import.meta.url);
class UniGraphics extends Component {
render() {
return (
<span>
<Header />
<p />
<Container maxWidth="md">
<Card>
<CardHeader title="University Graphics Project" />
<CardContent>
<Typography variant="p">
I made this project for a module at uni. It's a terrain map
based on Perlin noise with flat face lighting, It was the first
project where I picked up a lot of the 3D maths used in games
and learned about simulation. It was my first project using
GLSL with C++ and also the project I optimised for an
optimiseation module in my final year. Getting deep into
learning more about memory management and Object-Oriented
design.
</Typography>
<p />
<Typography variant="p">
Here's a build and a video demo: &#8194;
<Button
variant="contained"
color="primary"
href={graphicsDemoBuild}
>Win64-Build.zip</Button>
</Typography>
<p />
<div>
<video controls loop muted autoPlay={true} style={{
width: "100%",
height: "auto",
objectFit: "cover",
}}>
<source src={graphicsDemoMp4} type="video/mp4" />
</video>
</div>
</CardContent>
</Card>
</Container>
</span>
);
}
}
export default UniGraphics;

View file

@ -1,43 +0,0 @@
import { h, render, Component } from "preact";
//import React from "react";
import Hls from "hls.js";
const PortfolioVideo = new URL("../static/video/background_video/index.m3u8", import.meta.url);
export default class VideoPlayer extends Component {
state = {};
// componentDidUpdate() {
componentDidMount() {
const video = this.player;
const url = PortfolioVideo.href; //"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8";
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(url);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = url;
video.addEventListener("loadedmetadata", function() {
video.play();
});
}
}
render() {
return (
<video
style={{
position: "absolute",
width: "100%",
height: "100%",
objectFit: "cover",
}}
loop
muted
className="videoCanvas"
ref={(player) => (this.player = player)}
autoPlay={true}
/>
);
}
}

View file

@ -1,53 +0,0 @@
import { h, render, Component } from "preact";
import {
Container,
Paper,
Card,
CardHeader,
CardMedia,
CardActions,
CardContent,
Typography,
Button,
} from "@material-ui/core";
import RambleScreenshot from "../static/images/RambleScreenshot.png";
class WebProjects extends Component {
render() {
return (
<Container>
<p />
<Card>
<CardHeader title="Web Development Projects" />
</Card>
<p />
<Card>
<CardHeader
title="ramble.fm"
subheader="Ramble Media LTD - Fullstack Web Developer: ReactJS,
NodeJS, Janus Media Server, Docker..."
/>
<CardMedia
style={{ height: 0, paddingTop: "25%" }}
image={RambleScreenshot}
title="ramble.fm"
/>
<CardContent>
<Typography variant="body1">
In this project, I was the CTO and built a website that allowed
users to stream their podcasts live and accept call-ins in a
similar vein to talk shows! I learnt the entire javascript web
development stack from React to audio streaming to DevOps in
order to make it a reality.
</Typography>
</CardContent>
<CardActions>
<Button href="/ramble" color="primary">
Learn More
</Button>
</CardActions>
</Card>
</Container>
);
}
}
export default WebProjects;

View file

@ -1,53 +0,0 @@
import { h, render, Component } from "preact";
import Router from "preact-router";
import AsyncRoute from "preact-async-route";
import { ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import Background from "./Background"
import Home from "./Home";
import theme from "./theme";
import "fontsource-roboto";
class App extends Component {
render() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Router>
<Home path="/" />
<AsyncRoute path="/research" getComponent={() =>
import("./Research").then((module) => module.default)
}
/>
<AsyncRoute path="/contact" getComponent={() =>
import("./Contact").then((module) => module.default)
}
/>
<AsyncRoute path="/ramble" getComponent={() =>
import("./Ramble").then((module) => module.default)
}
/>
<AsyncRoute path="/monq" getComponent={() =>
import("./Monq").then((module) => module.default)
}
/>
<AsyncRoute path="/uni-graphics" getComponent={() =>
import("./UniGraphics").then((module) => module.default)
}
/>
<AsyncRoute path="/graphics-blog" getComponent={() =>
import("./GraphicsBlog").then((module) => module.default)
}
/>
<AsyncRoute default getComponent={() =>
import("./404Page").then((module) => module.default)
}
/>
</Router>
<Background />
</ThemeProvider>
);
}
}
render(<App />, document.body);

View file

@ -1,36 +0,0 @@
import { createTheme } from "@material-ui/core/styles";
const bg_0h = { main: "#1d2021", contrastText: "#282828" };
const bg = { main: "#282828", contrastText: "#282828" };
const red = { main: "#fb4934", contrastText: "#282828" };
const green = { main: "#b8bb26", contrastText: "#282828" };
const yellow = { main: "#fabd2f", contrastText: "#282828" };
const blue = { main: "#83a598", contrastText: "#282828" };
const purple = { main: "#d3869b", contrastText: "#282828" };
const aqua = { main: "#8ec07c", contrastText: "#282828" };
const gray = { main: "#a89984", contrastText: "#282828" };
const orange = { main: "#8ec07c", contrastText: "#282828" };
const fg = { main: "#ebdbb2", contrastText: "#282828" };
const theme = createTheme({
palette: {
type: 'light',
primary: {
main: '#00a878',
},
secondary: {
main: '#046865',
},
background: {
default: '#f0ffd6',
},
error: {
main: '#e53d00',
},
warning: {
main: '#ffe900',
},
}
});
export default theme;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View file

@ -1,86 +0,0 @@
// create background element
let canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.style.cssText = `
background: #f0ffd6;
position:fixed;
left:0;
top:0;
z-index:-99999;
`
// set it's size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let context = canvas.getContext('2d');
// this will be populated and used later
drawableObjectList = [];
// this is the object that'll look cool
class Point {
constructor() {
this.x = Math.random() * window.innerWidth;
this.y = Math.random() * window.innerHeight;
this.dx = (Math.random()) - 0.5;
this.dy = (Math.random()) - 0.5;
}
draw() {
context.fillStyle = "#00a878"
context.strokeStyle = "#00a878"
// find and draw links
drawableObjectList.forEach((point) => {
if (point.x > this.x - 100 && point.x < this.x + 100 &&
point.y > this.y - 100 && point.y < this.y + 100) {
context.beginPath()
context.moveTo(this.x, this.y)
context.lineTo(point.x, point.y)
context.stroke();
}
});
// draw point
context.beginPath();
context.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
context.fill();
context.stroke();
// move point
this.x += this.dx;
this.y += this.dy;
// keep point in bounds
if (this.x > window.innerWidth || this.x < 0) {
this.dx *= -1
}
if (this.y > window.innerHeight || this.y < 0) {
this.dy *= -1
}
}
}
// populate element array
for (let i = 0; i < 100; i++) {
drawableObjectList.push(new Point());
}
function loop() {
// Loop and clear frame
requestAnimationFrame(loop);
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
// Draw objects.
drawableObjectList.forEach((point) => {
point.draw();
});
// Handle page size change
if (canvas.width != window.innerWidth) {
canvas.width = window.innerWidth;
}
if (canvas.height != window.innerHeight) {
canvas.height = window.innerHeight;
}
}
loop();

View file

@ -1,19 +0,0 @@
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:17
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:11.233333,
index0.ts
#EXTINF:9.466667,
index1.ts
#EXTINF:16.666667,
index2.ts
#EXTINF:8.333333,
index3.ts
#EXTINF:8.333333,
index4.ts
#EXTINF:6.433333,
index5.ts
#EXTINF:0.200000,
index6.ts
#EXT-X-ENDLIST

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.